Git Rebase 从带有 Squashed 合并的分支
Posted
技术标签:
【中文标题】Git Rebase 从带有 Squashed 合并的分支【英文标题】:Git Rebase from a branch with Squashed merges 【发布时间】:2021-12-14 07:13:40 【问题描述】:假设我已经提交了我的dev
分支,
a
b
c
我向main
分支发出拉/合并请求,并打开了壁球合并选项。
所以main
分支现在看起来像,
merge from 'dev' to 'main'
squash: a, b, c
但我的源分支dev
仍然是三个单独的提交。当我在 dev
分支上执行 git rebase main
时,这可能是一个问题,尤其是当 main
分支塞满了其他开发人员的压缩合并时。
通常,我会 cherry-pick
我的提前提交到 dev_bak
分支。删除我当前的分支dev
并通过这样做重新发布它
git switch [any-branch]
git branch -d dev // delete dev branch
git checkout -b dev // re-create dev branch
git rebase main // do rebase
git push --force // force push to remote to overwrite
然后将我的提前提交挑选回dev
分支。
所以我想知道是否有一种快速的方法可以做到这一点?或许是git rebase --force
?
谢谢!!
【问题讨论】:
【参考方案1】:您最好的选择是不要对您不删除的分支使用 squash 合并。壁球合并丢弃了分支上的历史;无论如何,只有当您要删除该分支时才有意义。对于长时间运行的分支,最好创建一个合并提交,以便记录分支之间的关系。
因为 squash 合并不会记录合并了哪些提交,如果您继续使用分支,则需要手动跟踪。
如果您可视化您拥有的提交图以及您正在尝试创建的内容,那么您可以计算出要使用的变基命令 - 这不是“强制”变基,而是告诉 git 您想要保留哪些提交。
假设我们从这个开始:
... <--A <--B <--C <--D <--E <--F
^ ^
main dev
然后你将 dev 压缩合并到 main(提交 DEF),并继续提交到 dev:
... <--A <--B <--C <--D <--E <--F <--G <--H
\ ^
<-- DEF dev
^
main
你想要结束的是这个(提交 GR 和 HR 分别重新创建 G 和 H 的更改):
... <--A <--B <--C
\
<-- DEF <--GR <--HR
^ ^
main dev
git rebase
有一个三参数形式,我将其读作“从 old_base 重新提交提交到 new_base”:git rebase old_base tip --onto new_base
(有些人更喜欢将 --onto new_base
放在首位,这真的没关系)。
所以在这种情况下,我们想要“将 F 到 H 的提交变基到 DEF 上”(因为 F 是我们压缩的最后一个提交):
git rebase F H --onto DEF
由于我们有一些分支指针,我们只需要查找 F 的提交哈希,就可以这样写:
git rebase F dev --onto main
【讨论】:
【参考方案2】:首先,让我们可视化您的场景:
o---o---o-----S (main)
\
A---B---C (dev)
提交S
是将A
、B
和C
压缩为单个提交并将其应用于目标分支(又名“挤压合并”)的结果。
现在,您所指的问题是由于 S
与原始提交 A
、B
和 C
无关,即使它包含同样的变化。在 main
之上重定 dev
会导致合并冲突,因为 Git 会尝试在压缩的提交之上重新应用相同的更改。
您要查找的命令是 reset
和 --hard
选项:
git switch dev
git reset --hard main
这将移动dev
分支以指向与main
相同的提交:
o---o---o-----S (main, dev)
\
A---B---C
提交 A
、B
和 C
现在将变为 unreachable 并最终将被删除。
请注意,--hard
选项还将同步您工作目录中的文件以匹配您要重置的提交。这意味着当您执行此操作时,您的工作目录中任何未提交的更改都将被丢弃。在执行git reset --hard
之前,请确保将它们存储或提交到临时分支。
【讨论】:
以上是关于Git Rebase 从带有 Squashed 合并的分支的主要内容,如果未能解决你的问题,请参考以下文章