错误合并后重建git分支(尊重合并提交)

时间:2019-07-04 16:57:30

标签: git merge rebase

我有一个典型的情况:我将一个dev分支合并到master中,然后意识到我犯了一个错误并恢复了合并。然后将修订添加到dev中,并希望再次合并。当然,我不能直接合并它,因为从git的角度来看,它已经被合并了。

经典解决方案

还原还原提交,应用您的修复程序。继续前进。

  • 优点:简单。

  • 缺点:历史被宠坏了。很难指责比这次还原还深。

我想要的

我想从头开始重建dev分支,然后再次合并。根据书中所述,应使用git rebase --force-rebase轻松完成。但是分支的历史记录并不是那么简单,它包含许多合并,包括来自master的合并。我要尊重这些。

让我们举个例子:

                                     master|
                                           v
-*------------X-----Y---------*-----*----M-W
  \          /       \         \   /    /
   \        /         \         -*-    /
    \      /  -D-      G--H--         /
     \    /  /   \    /      \       /
------A--B--C-----E--F--------I-----J
                                    ^
                                    |dev

错误的合并是M。其还原为W。我认为在devB上的提交都是可以的,因为B已作为master合并到X中。我想以完全相同的拓扑重建从B开始的分支。请参阅下面的树。新提交标记有撇号。您可以看到如何将提交C..J重构为C'..J'。相应地,dev被重设为dev'。其他提交未更改。在这里,我仅在重新设置基础之前部分描绘了dev,以免在图纸上造成太多麻烦。它隐藏在省略号...后面。

                ...-F-G-...           master|
                     /                      v
-*------------X-----Y---------*-----*-----M-W
  \          /       \         \   /     /   
   \        /         \         -*-     /   
    \      /  -D'      G'-H'-      ...-J <-dev
     \    /  /   \    /      \           
------A--B--C'----E'-F'-------I'----J'
          \                         ^
           C-...                    |dev'

然后,我将应用修订K并将此新分支合并到master

                ...-F-G-...                  master|
                     /                             v
-*------------X-----Y---------*-----*-----M-W------M2
  \          /       \         \   /     /        /
   \        /         \         -*-     /        /
    \      /  -D'      G'-H'-      ...-J <-dev  /
     \    /  /   \    /      \                 /
------A--B--C'----E'-F'-------I'----J'--------K
          \                                   ^
           C-...                              |dev'

  • 优点:良好的历史记录。

  • 缺点:我不知道该怎么做。

好吧,似乎rebase对此有一个选择,它被称为--rebase-merges。但这并不能满足我的要求。它将所有作为dev的祖先和B的后代的提交作为基准。其中包括提交XYmaster上已经有哪些,我为什么要它们? (实际上,它还带来了更古老的历史中的其他一些贡献,我还不知道为什么,但这不是重点)。

相反,我想带的是dev而不是master 的祖先的提交(当然,在错误合并之前考虑master)。对我来说听起来真的很容易。但是我不知道该怎么做,只能通过手工构造这种不同的提交,并以某种方式手工挑选它们,并小心翼翼地保护父母。

那么,如何重建分支,只包含在分支上完成的工作并尊重合并提交?

PS 我们不能简单地将master重设为M^,这太容易了。

2 个答案:

答案 0 :(得分:0)

基于https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt,我会

git checkout dev
$EDITOR files
git commit files -m 'Fix'
git checkout master
git revert W
git merge dev

当您重新合并时,保留还原更改是必要的。

答案 1 :(得分:0)

好吧,好像我找到了解决方法:

  1. git rebase --interactive --rebase-merges B dev
  2. reword C

这恰好产生了我想要的历史记录。归功于@mstrap作为提示。

我不确定为什么它能按我想要的方式工作。