撤消尚未推送的 Git 合并

在我的 master 分支中,我在本地进行了git merge some-other-branch ,但从未将更改推送到原始 master。我不是要合并,所以我想撤消它。合并后执行git status ,收到以下消息:

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

根据我发现的一些说明 ,我尝试运行

git revert HEAD -m 1

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

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

我不希望我的分支领先于任何数量的提交。我如何回到这一点?

答案

使用git reflog检查哪个提交是合并之前的提交( git refloggit log更好的选择)。然后您可以使用以下方法重置它:

git reset --hard commit_sha

还有另一种方法:

git reset --hard HEAD~1

它将使您退回 1 次提交。

请注意,任何已修改和未提交 / 未破坏的文件都将重置为其未修改状态 。要保留它们,可以--merge更改,或参见下面的--merge选项。


正如 @Velmont 在下面的回答中所建议的,在这种直接情况下,使用:

git reset --hard ORIG_HEAD

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


另一个提示是使用--merge开关而不是--hard因为它不会不必要地重置文件:

git reset --merge ORIG_HEAD

- 合并

重置索引并更新工作树中 和 HEAD 之间不同的文件,但保留那些索引和工作树中不同的文件(即,尚未添加的更改)。

假设您的本地主人不在原产地 / 主人之前,那么您应该可以

git reset --hard origin/master

然后,您的本地master分支应该看起来与origin/master相同。

请参阅Git 书中的第 4 章和 Linus Torvalds 的原始帖子

撤消已经推送的合并:

git revert -m 1 commit_hash

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

最简单的命令丢失了很奇怪。大多数答案都有效,但是撤消您刚才所做的合并, 这是简单安全的方法

git reset --merge ORIG_HEAD

引用ORIG_HEAD将指向合并之前的原始提交。

--merge选项与合并无关。就像git reset --hard ORIG_HEAD ,但是更安全,因为它不会涉及未提交的更改。)

使用较新的 Git 版本,如果您尚未提交合并,但是发生合并冲突 ,则可以执行以下操作:

git merge --abort

来自man git merge

[this] 仅在合并导致冲突后才能运行。 git merge --abort将中止合并过程,并尝试重建合并前的状态。

您应该重置为上一次提交。这应该工作:

git reset --hard HEAD^

甚至HEAD^^可以还原该还原提交。如果您不确定应该返回多少步骤,可以始终提供完整的 SHA 参考。

万一遇到问题,而 master 分支没有任何本地更改,则可以重置为origin/master

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

git reflog可能返回类似以下内容:

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

第一行表示发生了合并。第二行是我合并之前的时间。我只是git reset --hard 43b6032强制该分支从合并和随身携带之前跟踪。

使用现代 Git,您可以:

git merge --abort

较旧的语法:

git reset --merge

老套:

git reset --hard

但实际上,值得注意的是, MERGE_HEAD存在git reset --mergegit merge --abort仅等效于git reset --merge 。可以在 Git 帮助中的合并命令中阅读。

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在日常工作中git reset --merge起来更强大,更有用,所以我一直使用它。

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

这样做...

git reset --hard HEAD^
git status

... 给我以下状态。

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

然后,我不得不多次输入相同的git reset命令。每次执行此操作时,该消息都会变成一个,如下所示。

> 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 ,这似乎可行:

> 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

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

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull

您可以使用git reflog查找先前的结帐。有时候,这是您想要返回的良好状态。

具体来说,

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