回滚Git合并


225
develop branch
--> dashboard (working branch)

git merge --no-ff develop过去将任何上游更改合并到仪表板中

git日志:

commit 88113a64a21bf8a51409ee2a1321442fd08db705
Merge: 981bc20 888a557
Author: XXXX <>
Date:   Mon Jul 30 08:16:46 2012 -0500

    Merge branch 'develop' into dashboard

commit 888a5572428a372f15a52106b8d74ff910493f01
Author: root <root@magneto.giveforward.com>
Date:   Sun Jul 29 10:49:21 2012 -0500

    fixed end date edit display to have leading 0

commit 167ad941726c876349bfa445873bdcd475eb8cd8
Author: XXXX <>
Date:   Sun Jul 29 09:13:24 2012 -0500

合并中包含约50多个提交,我想知道如何仅还原合并,以便仪表板返回到合并前的状态

第二部分是,如果不合并--no-ff,就不会提交' 合并分支'开发'到仪表板 '..我如何回滚合并?


3
撤销Git合并可能重复吗?

Answers:


320

其他问题已详尽介绍了还原合并提交在进行快速合并时,即您描述的第二个合并,您可以git reset用来返回到先前的状态:

git reset --hard <commit_before_merge>

您可以<commit_before_merge>使用git reflog,,git log或查找,如果您感觉很烦躁(并且没有做任何其他事情):git reset --hard HEAD@{1}


6
感谢您的快速回复..查看git日志,合并之前的提交是50+次提交,因为git merge development实际上会放入所有其他提交。如果我不知道合并的内容/位置,我想我不会明白的是-我怎么找到它?您提到找到了commit_before_merge ..我想我不理解该部分
cgmckeever 2012年

4
看起来像git reflog一样,它很好地总结了最后的头,并让我知道需要重置到的位置。git log似乎有太多的粒度,无法确定要重置到的位置。谢谢
cgmckeever

1
是的,reflog是救星。HEAD@{1}只是描述了HEAD的第二最新状态,或更具体地讲,是:“带有后缀@的ref后跟带有大括号对的序号规范(例如{1},{15})指定了HEAD的第n个优先值参考。”
Christopher

4
将推送到远程该怎么办?我不知道它将如何工作。
安东·萨维利耶夫

2
这是没有希望的。合并后销毁所有提交。
aaa90210

151

从这里:

http://www.christianengvall.se/undo-pushed-merge-git/

git revert -m 1 <merge commit hash>

Git恢复添加了一个新的提交,该提交将回滚指定的提交。

使用-m 1表示这是一次合并,我们想回滚到master分支上的父提交。您将使用-m 2指定develop分支。


30
请注意,此后您不能重新合并分支,因为文档说:“还原合并提交声明您将永远不希望合并带来的树更改。因此,以后的合并只会引入引入的树更改不是先前还原的合并的祖先的提交。这可能是您想要的,也可能不是您想要的。”
达利波·卡洛维奇

23
@DaliborKarlović这句话有点苛刻。您一定可以稍后再带回那些更改,诀窍是还原还原提交。更多信息这里在部分“还原的还原”
Hilikus

3
可悲的是,here@ Hilikus注释中的链接不再有效。该网站声称内容已移至一本书(git-scm.com/book/en/v2),但如果是这样,在其中查找内容并非易事
杰西·奇斯霍尔姆

@DaliborKarlović是@Christopher的上述回答的案子吗?
詹姆士·B

3
撤消合并的内容已移至此处
-SEK

27

只需使用重置合并提交git reset --hard HEAD^

如果您使用--no-ff git,即使您之间没有提交任何内容,git也会始终创建合并。没有--no-ff git只会进行快进,这意味着您的分支HEAD将设置为合并分支的HEAD。要解决此问题,请找到您想要还原为的提交ID git reset --hard $COMMITID


1
如果您在合并之前不知道提交,那将是一个很好的解决方案。
iglesiasedd

为我工作,因为我不知道提交ID。+ 1
Anant Singh ---死于

如果不需要的合并已经提交给远程,则我使用git push -f在还原后更新远程分支。
zumek

16
git revert -m 1 88113a64a21bf8a51409ee2a1321442fd08db705

但是可能会有意想不到的副作用。请参阅git-scm.com/docs/git-revert中的--mainline parent-number选项

也许一种蛮有用但有效的方法是检出该提交的左父项,制作所有文件的副本,HEAD再次检出,并将所有内容替换为旧文件。然后git会告诉您正在回滚的内容,然后您创建自己的还原提交:)!


1
+1,因为此答案不会像重置一样弄乱历史记录(如果您已经推送到远程,则非常重要)。但是我应该期待什么意外的副作用?
pedromanoel

3
这是您提到的副作用吗? Reverting a merge commit declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge. This may or may not be what you want.
pedromanoel

1
您说的git reset是解决方案,但同时也提到它可能会有意想不到的副作用。但是,该链接来自git revert,而不是git reset:)
马克

2
请注意,git reset没有-m标志。另请注意,@ JorgeOrpinel引用的是git-revert文档,而不是git-reset。我想他的意思是说git revert没有git reset
德文-格里森兰伯特

如何避免指定Mainline但提交1234xyz不是合并错误。
Achal

0

如果合并分支,则使用拉取请求还原合并,然后合并该拉取请求以还原。

我觉得最简单的方法是:

  1. 从develop / master(合并的地方)中取出一个新分支
  2. 使用git revert -m 1 xxxxxx(如果还原是通过分支合并的)还原“还原”,或者使用git revert xxxxxx简单还原
  3. 现在,新分支应该具有您想要再次合并的更改。
  4. 进行更改或合并此分支以开发/掌握
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.