撤销一个尚未推送的 Git 合并操作

4847

我不小心在本地主分支上运行了git merge some_other_branch。我还没有将更改推送到origin主分支。如何撤消合并?


合并后,git status显示:

# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.

如何撤销所有这些提交?


3
如果您需要保留历史记录,换句话说,如果有任何人曾经从您那里拉过或者您已经将其推到其他地方,请使用Yuri Ushakov在下面回答中提供的解决方案! - Sedrik
6
请取消当前获胜的答案,因为许多人指出它是不安全的,尽管仍在收集投票。对我来说,“MBO”看起来最好,尽管得分要少得多。 - inger
5
如果您需要保留历史记录,请使用下面 Yuri 的解决方案(在 @Sedrik 的评论中添加了一个链接)。 - cregox
相关:回退到之前的Git提交 - user456814
4
这是一个来自Github的很棒的资源: 使用Git撤销(几乎)任何操作 - jasonleonhard
Git - 三棵树的故事(头部、索引和工作树以非常有帮助的方式解释):重置解密 - leanne
35个回答

12

最简单的答案是odinho-Velmont给出的答案。

首先执行git reset --merge ORIG_HEAD

对于那些想要在推送更改后重置的人,请执行以下操作 (因为这是任何git reset合并问题的第一篇帖子)

git push origin HEAD --force

这将以一种方式重置,以便在拉取后不会再次获得合并的更改。


11

仅供参考,我一直遵循在此处描述的分支模型:http://nvie.com/posts/a-successful-git-branching-model/,因此通常会使用--no-ff(不快进)合并。

我刚刚阅读了这个页面,因为我不小心将测试分支与主发行版的master分支合并,以进行部署(网站上的master即为现行版本)。 测试分支已合并另外两个分支,总共有约六个提交。

因此,要还原整个提交,我只需要使用git reset --hard HEAD^,它就会还原整个合并操作。由于合并不是快进式合并,所以该合并是一个块,退回一步即是“未合并的分支”。


10
使用此命令中止合并操作:
git merge --abort

9
如果您的合并和相应的提交尚未推送,则可以随时切换到另一个分支,删除原始分支并重新创建它。 例如,我不小心将develop分支合并到master分支中,并希望撤销该操作。按照以下步骤:
git checkout develop
git branch -D master
git branch -t master origin/master

看,主分支和原来的状态一样了,你的错误合并已经被消除了。


1
注意:这不仅会撤销合并,还会撤销自最后一次推送到远程之后所做的任何本地提交。 - Martijn Heemels

6

策略:从一切正常的地方创建一个新分支。

原因:回滚合并很困难。有太多的解决方案,取决于许多因素,例如您是否提交或推送了合并,或者是否有新的提交自您合并以来。此外,您仍需要相对深入地了解git将这些解决方案适应于您的情况。如果您盲目地按照某些说明操作,则可能会出现“空合并”,其中没有任何内容将被合并,并且进一步的合并尝试将使Git告诉您“已经是最新的”。

解决方案:

假设您想将dev合并到feature-1中。

  1. Find the revision that you want to receive the merge:

    git log --oneline feature-1
    a1b2c3d4 Merge branch 'dev' into 'feature-1' <-- the merge you want to undo
    e5f6g7h8 Fix NPE in the Zero Point Module <-- the one before the merge, you probably want this one
    
  2. Check it out (go back in time):

    git checkout e5f6g7h8
    
  3. Create a new branch from there and check it out:

    git checkout -b feature-1
    
现在您可以重新开始合并:
  1. 合并:git merge dev

  2. 解决您的合并冲突。

  3. 提交:git commit

  4. 当您对结果满意时,删除旧分支:git branch --delete feature-1


5

只需创建新分支,然后将所需提交(cherry-pick)到该分支即可。

这比上面许多答案中描述的重置(resets)更安全简单。


2
我同意这个建议,特别是如果你对列出的 git 命令不是完全熟悉。尽管这可能会更加“费力”,但如果它不经常出现并且你担心丢失工作,那么这将是值得付出的努力。 - Greg

5
如果你想要一个命令行的解决方案,我建议你选择MBO的答案。
如果你是一个新手,也许你会喜欢图形化的方法:
1.启动gitk(在命令行中,或者如果你有文件浏览器,请右键单击)。
2.你可以很容易地发现合并提交 - 从上面开始的第一个带有两个父节点的节点。
3.跟随链接到第一个/左侧的父节点(合并前你当前分支上的那个节点,通常对于我来说是红色的)。
4.在选定的提交上,右键单击"Reset branch to here",选择强制重置。

3
我认为您可以执行git rebase -i [hash] [branch_name],其中[hash]是您想要倒回的标识哈希值加一(或者您想要回退的提交数量),然后在编辑器中删除您不再需要的提交行。保存文件。退出。祈祷。这样就应该回退了。您可能还需要执行git reset --hard,但此时应该已经完成了。您也可以使用此方法从堆栈中提取特定的提交,如果您不想将它们保留在历史记录中,但这可能会使您的存储库处于您可能不想要的状态。

只有一个细节,交互式变基允许通过删除行来删除提交,但如果您删除所有内容,则变基将被简单地中止。这里最简单的技巧是删除除一行之外的所有行,并将此最后一行标记为“drop”,以便丢弃所有内容。 - jesjimher

2
  1. First, make sure that you've committed everything.

  2. Then reset your repository to the previous working state:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

    or using --hard (this will remove all local, not committed changes!):

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

    Use the hash which was there before your wrongly merged commit.

  3. Check which commits you'd like to re-commit on the top of the previous correct version by:

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  4. Apply your right commits on the top of the right version of your repository by:

    • By using cherry-pick (the changes introduced by some existing commits)

          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
      
    • Or by cherry-picking the range of commits by:

      • First checking the right changes before merging them:

        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        
      • First checking the right changes before merging them:

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

        where this is the range of the correct commits which you've committed (excluding wrongly committed merge).


1
  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

这对我有用..!!


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