修改使用合并以使用rebase的git主题分支的历史记录

时间:2012-06-20 06:53:57

标签: git git-merge git-rebase

我们的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 rebasegit rebase -p命令而没有运气。

2 个答案:

答案 0 :(得分:4)

我发现以下过程似乎工作得相当好,但并不完美。可能需要一些小的冲突解决方案 - 见下文。

  1. 通过从master进行最终合并,确保主题分支与最新的master是最新的(如果尚未完成):

    git checkout topic
    git merge master
    
  2. 通过排除合并来简化主题分支的历史记录:

    git log --no-merges
    
  3. 从上面的日志中,确定分支点(第一个主题分支提交之前的master上的提交,应该提交F)。

  4. 将主题分支重新定位到主服务器上,忽略合并(这是默认设置,即不使用--preserve-merges / -p选项),解决任何冲突

    git checkout master
    git rebase --onto HEAD F topic
    

    我发现在重新定位期间,通常会发生冲突会导致文件处于冲突的“两个已修改”状态,但它不包含冲突标记,因此简单的git addgit rebase --continue是足以解决冲突并继续下去。我相信git正在使用之前的解决方案来解决冲突。

    此外,在一些更复杂的分支中,将需要多个git rebase --onto HEAD ...命令,或者git cherry-pick可用于挑选单个提交。只需完成步骤2中给出的日志,根据需要将范围重新定位到HEAD和/或可能挑选个别提交。

  5. 当前的HEAD现在应该代表重新定位的主题分支。通过检查diff导致无输出来验证结果是否与原始主题分支匹配:

    git diff topic..HEAD
    
  6. 将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,所以基本上抓住了我合并mastertopic的地方之间的提交范围。在我这样做的整个过程中,我处于超然的状态,所以如果你看到它就不要担心。有几次我有合并冲突,但它们都是我期望看到的合法冲突。

最后,我有一个看起来正确的分支(拉曼答案中的第6步),但由于某种原因,我不得不再次重新掌握到主人以实际移动提交。我不知道为什么我必须这样做,但它进展顺利。

我认为这样做基本上相当于采摘樱桃,所以反而可能更简单。