Git:如何“撤销”合并

17

情境: 从主代码 A 开始,我创建了一个分支并在B处进行了一些更改,然后合并了该分支回到(C)。在进行了一些其他更改后,我到达了 D,但发现需要部署没有分支更改的代码。如果我没有合并分支,那就没有问题。

A_______C___D
 \     /
  \_B_/

首先,我想知道我应该从这里做些什么,以便部署代码时就好像没有发生合并一样。注意:分支中编辑过的所有文件在主分支中都没有进行过编辑。

其次...

我没有时间来找出处理这个问题的最佳方法,因此我删除了分支添加的文件,并手动还原了分支中进行的一些编辑,然后提交了结果以供部署(F)。

A_______C___D___F
 \     /
  \_B_/

我希望能够继续开发分支并将任何来自主分支的更改合并到分支中以保持更新,但如果我这样做,用于创建 F 的内容将被合并并导致文件被删除和编辑被还原。如何处理这个问题?

2个回答

16
您可以使用rebase一步完成此操作:
git rebase --onto A C D

我刚刚测试了一下,结果是正确的:

$ edit test.txt
$ git add .
$ git commit -mA
$ git checkout -b the_branch
$ edit test.txt
$ git commit -a -mB
$ git checkout master
$ git merge master the_branch --no-ff
$ edit test.txt
$ git commit -a -mD

从这里开始,您将遇到您描述的情况。然后:

$ git rebase --onto <SHA1-for-A> <SHA1-for-C> master

将从C(不包括)到主分支master的提交重新设置基础,然后合并到A上。 由于我在B和D中修改了同样的位置,所以需要解决一些冲突,但我认为您不需要。

   _D'
  /
 /
A_______C___D
 \     /
  \_B_/

以下是关于git rebase --onto的文档,它或多或少与您的情况相符:http://git-scm.com/docs/git-rebase


如果您有:

A_______C___D___F
 \     /
  \_B_/

如果您现在拥有:

   _D'___F'_(master)
  /
 /
A_______C___D___F
 \     /
  \_B_/(the_branch)

从这里开始,将主分支的更改合并到分支非常容易。完全放弃提交F'
$ git checkout master # if you were not here already
$ git branch old_fix  # if you want to be able to return to F' later
$ git reset --hard <SHA1-to-D'>

执行以上命令后,您将拥有:

     (master)
    /
   _D'___F'_(old_fix)
  /
 /
A_______C___D___F
 \     /
  \_B_/(the_branch)

将主分支的更新合并到 the_branch 分支中:
$ git checkout the_branch
$ git merge master

...并解决冲突。


太棒了,谢谢!如果更加小心合并失败的话,我会在未来使用这个。请参考@terminus的答案,我认为它实现了与你的答案几乎相同的结果。 - Jake

6
显而易见的解决方案是重置为A,手动重新应用所有补丁并解决冲突(你不会有冲突)。
或者您可以只使用git revert补丁B,但这将创建一个新的提交。
尽管Gauthier的答案更好。

谢谢,读完这个之后,我查看了一下补丁,并最终找到了这个链接:http://www.gitready.com/intermediate/2009/03/04/pick-out-individual-commits.html 所以我从分支A切出一个新分支,选择了提交记录D和F,然后将结果合并到原来的分支中,以使其保持最新。 - Jake
你真的挑选了 F 吗?我以为 F 只是为了反转 B 和 C,所以在 C' 之后没有任何作用。 - Gauthier
抱歉,现在我不确定。也许我做了,但实际上并不需要。 - Jake

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接