撤消尚未推送的Git合并

Undo a Git merge that hasn't been pushed yet

在我的主分支中,我在本地执行了一个git merge some-other-branch,但从未将更改推到原始主。我不是有意合并,所以我想撤销它。合并后做git status的时候,我得到的信息是:

1
2
# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.

根据我发现的一些指示,我试着跑步

1
git revert HEAD -m 1

但现在我收到了git status的消息:

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

我不希望我的分支机构在任何数量的承诺方面领先。我该怎么回到这一点?


使用git reflog检查合并前的承诺(git reflog将是比git log更好的选择)。然后您可以使用以下方法重置它:

1
git reset --hard commit_sha

还有另一种方法:

1
git reset --hard HEAD~1

它将使你返回1个承诺。

请注意,任何已修改和未提交/未显示的文件都将重置为未修改状态。为了不让他们改变藏匿或见下面的--merge选项。

正如@velmont在他的回答中建议的,在这个直接案例中使用:

1
git reset --hard ORIG_HEAD

可能会产生更好的结果,因为它应该保留您的更改。ORIG_HEAD将直接指向合并发生之前的提交,因此您不必自己寻找它。

另一个技巧是使用EDOCX1开关(5)而不是EDOCX1开关(8),因为它不会不必要地重置文件:

1
git reset --merge ORIG_HEAD

--merge

Resets the index and updates the files in the working tree that are different between and HEAD, but keeps those which are different between the index and working tree (i.e. which have changes which have not been added).


假设您的本地主机不在源站/主机之前,您应该能够

1
git reset --hard origin/master

那么你当地的master分公司应该和origin/master一模一样。


见Git手册第4章和Linus Torvalds的原始帖子。

要撤消已推送的合并,请执行以下操作:

1
git revert -m 1 commit_hash

如Linus所说,如果您再次提交分支,请确保恢复还原。


奇怪的是,最简单的命令丢失了。大多数答案都有效,但是撤销刚才的合并,这是一种简单而安全的方法:

1
git reset --merge ORIG_HEAD

参考文件ORIG_HEAD将指向合并前的原始提交。

(--merge期权与合并无关。它就像git reset --hard ORIG_HEAD,但更安全,因为它不涉及未承诺的更改。)


对于较新的Git版本,如果尚未提交合并,并且存在合并冲突,则只需执行以下操作:

1
git merge --abort

来自man git merge

[This] can only be run after the merge has resulted in conflicts. git merge --abort will abort the merge process and try to reconstruct the pre-merge state.


您应该重置为上一个提交。这应该有效:

1
git reset --hard HEAD^

或者甚至使用HEAD^^来恢复该恢复提交。如果你不确定应该后退多少步,你可以给出一个完整的sha参考。

如果您有问题,并且您的主分支没有任何本地更改,可以重置为origin/master


最近,我一直在使用git reflog来帮助解决这个问题。只有合并刚刚发生,并且它在您的计算机上时,这才起作用。

git reflog可能返回如下内容:

1
2
3
4
5
6
fbb0c0f HEAD@{0}: commit (merge): Merge branch 'master' into my-branch
43b6032 HEAD@{1}: checkout: moving from master to my-branch
e3753a7 HEAD@{2}: rebase finished: returning to refs/heads/master
e3753a7 HEAD@{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 HEAD@{4}: reset: moving to HEAD^
8400a0f HEAD@{5}: rebase: aborting

第一行指示发生了合并。第二行是我合并前的时间。我只是简单地强迫这个分支机构在合并前跟踪,然后继续。


使用Modern Git,您可以:

1
git merge --abort

旧语法:

1
git reset --merge

老派:

1
git reset --hard

但实际上,值得注意的是,考虑到MERGE_HEAD存在,git merge --abort只相当于git reset --merge。这可以在合并命令的git帮助中读取。

1
git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.

合并失败后,在没有MERGE_HEAD的情况下,可以用git reset --merge撤消合并失败,但不一定用git merge --abort撤消合并失败,因此它们不仅是同一事物的新旧语法。

就我个人而言,我发现git reset --merge在日常工作中更强大、更有用,所以我总是使用它。


好吧,这里其他人给我的答案很接近,但没用。我就是这么做的。

这样做…

1
2
git reset --hard HEAD^
git status

…给了我以下状态。

1
2
3
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.

然后,我不得不多次输入同一个git reset命令。每次我这样做,信息都会被一个改变,如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 1 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.

此时,我看到状态消息发生了变化,所以我尝试执行git pull,这似乎有效:

1
2
3
4
5
6
7
8
9
> git pull
Updating 2df6af4..12bbd2f
Fast forward
 app/views/truncated |    9 ++++++---
 app/views/truncated |   13 +++++++++++++
 app/views/truncated |    2 +-
 3 files changed, 20 insertions(+), 4 deletions(-)
> git status
# On branch master

长话短说,我的命令归结为:

1
2
3
4
5
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull


您可以使用git reflog查找上一次结账。有时候,这是一个很好的状态,你想回到。

具体地说,

1
2
$ git reflog
$ git reset --hard HEAD@{0}


如果尚未提交,则只能使用

1
$ git checkout -f

它将撤消合并(以及您所做的所有操作)。


要解决这个问题,还需要恢复到与源站匹配的状态(即,在源站之前没有提交)。进一步研究发现,有一个reset命令用于:

git reset --hard @{u}

注:@{u}origin/master的简称。(当然,您还需要这个远程存储库才能工作。)


为了获得一个额外的选择,我主要遵循这里描述的分支模型:http://nvie.com/posts/a-successful-git-branching-model/,因此通常与--no-ff合并(不快速前进)。

我刚刚阅读了这个页面,因为我意外地将一个测试分支而不是我的发布分支与用于部署的master合并了(网站,master是实时的)。测试分支还有两个合并到它的分支,总共大约有六个提交。

所以为了恢复整个承诺,我只需要一个git reset --hard HEAD^,它就恢复了整个合并。由于合并没有快速转发,合并是一个块,后退一步是"分支未合并"。


只能使用两个命令恢复合并或通过特定提交重新启动:

  • git reset --hard commitHash(您应该使用要重新启动的提交,例如44a587491e32eafa1638ac7738)
  • git push origin HEAD --force(将新的本地主分支发送到origin/master)
  • 祝你好运,继续!


    最简单的答案是奥迪尼奥-维尔蒙特给出的答案。

    先做git reset --merge ORIG_HEAD

    对于那些在推送更改后希望重置的用户,请执行此操作(因为这是所有Git重置合并问题的第一篇文章)

    git push origin HEAD --force

    这将以某种方式重置,这样拉后就不会再次获得合并的更改。


    我可以通过一个不涉及查找提交ID的命令来解决这个问题。

    1
    git reset --hard remotes/origin/HEAD

    被接受的答案对我来说不起作用,但这个命令实现了我想要的结果。


    如果您的合并和相应的提交还没有被推送,那么您总是可以切换到另一个分支,删除原来的分支并重新创建它。

    例如,我不小心将一个开发分支合并到master中,并想撤销它。使用以下步骤:

    1
    2
    3
    git checkout develop
    git branch -D master
    git branch -t master origin/master

    哇!master与origin处于同一阶段,您的错误合并状态将被清除。


    如果您正在进行合并,可以随时中止合并。git merge --abort


    策略:创建一个新的分支,从那里一切都很好。

    理由:恢复合并很困难。有太多的解决方案,这取决于许多因素,例如您是否提交或推动了合并,或者合并后是否有新的提交。此外,您还需要对Git有一个相对深入的了解,以使这些解决方案适合您的案例。如果你盲目地遵循一些指示,你可以以一个"空合并"结束,在那里什么都不会被合并,进一步的合并尝试将使git告诉你"已经是最新的"。

    解决方案:

    假设你想把dev合并成feature-1

  • 查找要接收合并的修订:

    1
    2
    3
    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
  • 查看(及时返回):

    1
    git checkout e5f6g7h8
  • 从那里创建一个新分支并签出它:

    1
    git checkout -b feature-1
  • 现在可以重新启动合并:

  • 合并:git merge dev

  • 修复合并冲突。

  • 承诺:git commit

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


  • 如果你想要一个命令行的解决方案,我建议你按照MBO的答案去做。

    如果你是新手,你可能会喜欢图形化的方法:

  • 启动gitk(从命令行,或右键单击文件浏览器,如果有的话)
  • 您可以很容易地在那里发现合并提交-从顶部的第一个节点有两个父节点
  • 沿着链接到第一个/左父级(合并前当前分支上的父级,我通常为红色)
  • 在选定的提交上,右键单击"重置分支到这里",在那里选择硬重置

  • 如果提交合并:

    1
    2
    3
    4
    git reset HEAD~1
    # Make sure what you are reverting is in fact the merge files
    git add .
    git reset --hard

  • 首先,确保你已经承诺了一切。

  • 然后将存储库重置为以前的工作状态:

    1
    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36

    或者使用--hard(这将删除所有本地的、未提交的更改!):

    1
    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard

    使用错误合并提交之前存在的哈希。

  • 通过以下方式检查要在以前正确版本的基础上重新提交的提交:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f

    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f

    ...

    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a

    ...
  • 在正确版本的存储库顶部应用您的权限提交,方法是:

    • 通过使用cherry pick(一些现有提交引入的更改)

      1
          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
    • 或者通过以下方式选择承诺范围:

      • 在合并之前首先检查正确的更改:

        1
        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
      • 在合并之前首先检查正确的更改:

        1
        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f

        其中,这是您已提交的正确提交的范围(不包括错误提交的合并)。


  • 我认为您可以执行git rebase -i [hash] [branch_name],其中[hash]是要倒带的多远的标识散列,加上一个(或多个要返回的提交),然后在编辑器中删除您不再需要的提交行。保存文件。出口。祈祷。它应该重绕。你可能需要做一个git reset --hard,但在这一点上应该是好的。如果不想将特定提交保存在历史记录中,也可以使用它将它们从堆栈中拉出,但这样会使存储库处于可能不需要的状态。


  • git stash

  • git branch -d the_local_branch

  • git checkout -t

  • git stash apply

  • 这对我很有用。!


    最简单的机会,比这里说的任何事情都简单:

    删除您的本地分支(本地,而不是远程),然后再次拉它。这样,您将撤消主分支上的更改,并且任何人都将受到您不想推动的更改的影响。从头开始。


    如果您注意到合并后需要立即恢复,并且在尝试合并后没有做任何其他操作,则可以发出以下命令:git reset --hard HEAD@{1}

    从本质上讲,如果合并后没有其他承诺,合并后的sha将指向HEAD@{0},因此HEAD@{1}将是合并前的前一点。


    在这种情况下,您需要使用git reset --hard 重置分支。如果要在重新设置之前保存更改,请确保创建新的分支和git checkout

    您也可以使用git reset --hard 将状态重置为特定的提交。

    如果已推动更改,则可以使用git revert 。一定要了解如何在其他场景中使用git revert和git check out。


    您可以使用git reset命令。

    git-reset - Reset current HEAD to the

    specified state. git reset [--mixed |

    --soft | --hard | --merge] [-q] [] git reset [-q] []

    [--] … git reset --patch

    [] [--] […]

    Git复位