我们的git开发工作流程是主题分支在最新的主服务器上不断重新定位,直到它们合并为止。
然而,一位新的开发人员已经创建了主题分支,在这些主题分支中,他已经将master与主题分支进行了多次合并,以使其保持最新状态。
A---B---C---D---E topic
/ / /
F---G---H---I master
虽然将此主题分支合并到master将是完全正确的,但它会导致非常混乱的历史记录。我想将这些主题分支转换为一个干净的线性重定历史,它可以通过单个--no-ff
合并提交完全合并到master中,即:
A'---B'---E' topic
/
F---G---H---I master
理想情况下,会有一些git-fu允许我执行rebase,按原样对主题分支进行提交,同时自动应用主题合并提交中已有的合并冲突解决信息,例如C和D.
我知道我可以简单地应用“git diff master..topic”的补丁,然后使用rebase向后工作并手动将单个补丁拆分为单独的提交,但是有更简单,更优雅的方法吗?
我已经尝试过直接git rebase
和git rebase -p
命令而没有运气。
答案 0 :(得分:4)
我发现以下过程似乎工作得相当好,但并不完美。可能需要一些小的冲突解决方案 - 见下文。
通过从master进行最终合并,确保主题分支与最新的master是最新的(如果尚未完成):
git checkout topic
git merge master
通过排除合并来简化主题分支的历史记录:
git log --no-merges
从上面的日志中,确定分支点(第一个主题分支提交之前的master上的提交,应该提交F)。
将主题分支重新定位到主服务器上,忽略合并(这是默认设置,即不使用--preserve-merges
/ -p
选项),解决任何冲突
git checkout master
git rebase --onto HEAD F topic
我发现在重新定位期间,通常会发生冲突会导致文件处于冲突的“两个已修改”状态,但它不包含冲突标记,因此简单的git add
和git rebase --continue
是足以解决冲突并继续下去。我相信git正在使用之前的解决方案来解决冲突。
此外,在一些更复杂的分支中,将需要多个git rebase --onto HEAD ...
命令,或者git cherry-pick
可用于挑选单个提交。只需完成步骤2中给出的日志,根据需要将范围重新定位到HEAD和/或可能挑选个别提交。
当前的HEAD现在应该代表重新定位的主题分支。通过检查diff导致无输出来验证结果是否与原始主题分支匹配:
git diff topic..HEAD
将HEAD命名为重新定位的主题分支名称:
git checkout -b rebased-topic
答案 1 :(得分:1)
拉曼的答案对我来说非常有用,但我想我会在第4步附加更多细节,这对我来说很棘手..
我有一个更复杂的回购,就像这样
Q-R-S-T-U-V-W-X
/ / / /
A-B-C-D-E-F-G-H-I-J-K
我想要这个:
Q'-R'-S'-T'-U'-V'-W'-X'
/
A-B-C-D-E-F-G-H-I-J-K
有效的做法是git rebase --onto HEAD Q R
,然后是git rebase --onto HEAD S U
,所以基本上抓住了我合并master
到topic
的地方之间的提交范围。在我这样做的整个过程中,我处于超然的状态,所以如果你看到它就不要担心。有几次我有合并冲突,但它们都是我期望看到的合法冲突。
最后,我有一个看起来正确的分支(拉曼答案中的第6步),但由于某种原因,我不得不再次重新掌握到主人以实际移动提交。我不知道为什么我必须这样做,但它进展顺利。
我认为这样做基本上相当于采摘樱桃,所以反而可能更简单。