我不小心在本地主分支上运行了 git merge some_other_branch
。我还没有将更改推送到原始主机。如何撤消合并?
合并后,git status
说:
# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.
我如何撤消所有这些提交?
使用 git reflog
检查哪个提交在合并之前(git reflog
将是比 git log
更好的选择)。然后您可以使用以下方法重置它:
git reset --hard commit_sha
还有另一种方式:
git reset --hard HEAD~1
它会让你回到 1 次提交。
请注意,任何已修改和未提交/未存储的文件都将重置为未修改状态。要让他们保留更改,或者查看下面的 --merge
选项。
正如@Velmont 在他的回答中建议的那样,在这种直接情况下使用:
git reset --hard ORIG_HEAD
可能会产生更好的结果,因为它应该保留您的更改。 ORIG_HEAD
将在合并发生之前直接指向提交,因此您不必自己寻找它。
另一个提示是使用 --merge
开关而不是 --hard
,因为它不会不必要地重置文件:
git reset --merge ORIG_HEAD
--merge 重置索引并更新工作树中
假设您的本地主人没有领先于原产地/主人,您应该能够做到
git reset --hard origin/master
然后您的本地 master
分支应该看起来与 origin/master
相同。
请参阅 chapter 4 in the Git book 和 the original post by Linus Torvalds。
要撤消已推送的合并:
git revert -m 1 commit_hash
如果您再次提交分支,请务必恢复还原,就像 Linus 所说的那样。
git revert -m 1 <commit>
。问题是这样做并没有消除他所做的意外合并(并且还没有推动)。涉及硬重置的其他答案更适合原始发布者的问题。
奇怪的是缺少最简单的命令。大多数答案都有效,但是撤消您刚刚所做的合并,这是一种简单而安全的方法:
git reset --merge ORIG_HEAD
ref ORIG_HEAD
将指向合并之前的原始提交。
(--merge
选项与合并无关。它就像 git reset --hard ORIG_HEAD
,但更安全,因为它不会触及未提交的更改。)
git reset --merge ORIG_HEAD
会保留这些更改。
git reset --hard HEAD~5
的命令只会重置 HEAD(可能会删除 master 和 branch1 中的提交)。只有 --merge
选项会删除 merge
。
--merge
选项实际上并没有删除合并,您可以使用 --hard
它也可以正常工作。此处的线索是参考 ORIG_HEAD,它是在您合并到您所在的位置之前设置的。 :)
git reset --hard ORIG_HEAD
命令对我来说非常有效——这可能是因为我在尝试撤消本地 git merge
后没有对存储库进行任何其他更改。该命令只是将存储库的状态重置为合并之前的状态。感谢您的精彩提示!
对于较新的 Git 版本,如果您尚未提交合并并且您有合并冲突,您可以简单地执行以下操作:
git merge --abort
从 man git merge
:
[This] 只能在合并导致冲突后运行。 git merge --abort 将中止合并过程并尝试重建预合并状态。
您应该重置为之前的提交。这应该有效:
git reset --hard HEAD^
甚至 HEAD^^
来恢复该恢复提交。如果您不确定应该退后多少步,您可以随时提供完整的 SHA 参考。
如果您遇到问题并且您的主分支没有任何本地更改,您可以重置为 origin/master
。
ORIG_HEAD
,为什么不使用它呢?
最近,我一直在使用 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
强制这个分支从合并之前开始跟踪,然后继续。
reflog
获取 SHA 并将其传递给 git reset
工作。
如果您正在合并,您可以随时中止它
git merge --abort
使用现代 Git,您可以:
git merge --abort
旧语法:
git reset --merge
老套:
git reset --hard
但实际上,值得注意的是,鉴于存在 MERGE_HEAD
,git 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 apply --3way
失败后,git reset --merge
提供了帮助,而其他答案却没有。这似乎是因为没有 MERGE_HEAD。
如果分支被合并而不被推送,那么下面给出的 git reset 命令将用于撤消合并:
git reset --merge ORIG_HEAD
例子:
git reset --merge origin/master
好的,这里其他人给我的答案很接近,但它不起作用。这就是我所做的。
这样做...
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
HEAD^^^^
origin/master
;)
你必须改变你的 HEAD,当然不是你的,而是 git HEAD....
所以在回答之前让我们添加一些背景知识,解释一下这个 HEAD
是什么。
首先什么是HEAD?
HEAD
只是对当前分支上当前提交(最新)的引用。
在任何给定时间只能有一个 HEAD
。 (不包括git worktree
)
HEAD
的内容存储在 .git/HEAD
中,它包含当前提交的 40 字节 SHA-1。
分离头
如果您不是最新的提交 - 这意味着 HEAD
指向历史上的先前提交,它称为 detached HEAD
。
https://i.stack.imgur.com/OlavO.png
在命令行上,它看起来像这样 - SHA-1 而不是分支名称,因为 HEAD
没有指向当前分支的尖端
https://i.stack.imgur.com/qplvo.png
关于如何从分离的 HEAD 中恢复的一些选项:
git结帐
git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back
这将签出指向所需提交的新分支。此命令将检出给定的提交。此时,您可以创建一个分支并从这一点开始工作。
# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>
# create a new branch forked to the given commit
git checkout -b <branch name>
git reflog
您也可以始终使用 reflog
。
git reflog
将显示更新 HEAD
的任何更改,并且检查所需的 reflog 条目会将 HEAD
设置回此提交。
每次修改 HEAD 时,reflog
中都会有一个新条目
git reflog
git checkout HEAD@{...}
这将使您回到所需的提交
https://i.stack.imgur.com/atW9w.png
git reset --hard
将您的 HEAD “移动”回所需的提交。
# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32
# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
注意:(从 Git 2.7 开始)您也可以使用 git rebase --no-autostash。
git revert
“撤消”给定的提交或提交范围。重置命令将“撤消”在给定提交中所做的任何更改。将提交带有撤消补丁的新提交,而原始提交也将保留在历史记录中。
# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>
此架构说明了哪个命令执行什么操作。
如您所见,reset && checkout
修改 HEAD
。
https://i.stack.imgur.com/NuThL.png
它可以通过多种方式完成。
1) 中止合并
如果您处于错误合并之间(错误地使用错误的分支完成),并且希望避免合并返回到最新的分支,如下所示:
git merge --abort
2) 将 HEAD 重置为远程分支
如果您在远程开发分支上工作,您可以将 HEAD 重置为远程分支上的最后一次提交,如下所示:
git reset --hard origin/develop
3)删除当前分支,并再次从远程存储库中签出
考虑到,您正在本地仓库中开发与远程/开发分支同步的分支,您可以执行以下操作:
git checkout master
##to delete one branch, you need to be on another branch, otherwise you will fall with the branch :)
git branch -D develop
git checkout -b develop origin/develop
git reset --hard origin/develop
这正是我要找的,谢谢!
您可以使用 git reflog
查找以前的结帐。有时那是你想要回到的一个很好的状态。
具体来说,
$ git reflog
$ git reset --hard HEAD@{0}
我能够通过一个不涉及查找提交 ID 的命令来解决这个问题。
git reset --hard remotes/origin/HEAD
接受的答案对我不起作用,但这个命令达到了我想要的结果。
如果你还没有提交,你只能使用
$ git checkout -f
它将撤消合并(以及您所做的一切)。
遇到这个问题也希望恢复到匹配原点(即,在原点之前没有提交)。进一步研究,发现有一个 reset
命令可以做到这一点:
git reset --hard @{u}
注意:@{u}
是 origin/master
的简写。 (当然,您需要该远程存储库才能正常工作。)
最简单的答案是 odinho - Velmont 给出的答案
首先执行git reset --merge ORIG_HEAD
对于那些希望在推送更改后重置的人,请执行此操作(因为这是任何 git reset 合并问题的第一篇文章)
git push origin HEAD --force
这将以一种在拉取后不会再次恢复合并更改的方式重置。
回答“撤消尚未推送的 Git 合并”问题
你可以使用 git reset --hard HEAD~1
考虑以下有 2 个分支 master 和 feature-1 的情况:
$ git log --graph --oneline --all
https://i.imgur.com/Yw9XS1y.png
做 Git 合并
$ git merge feature-1
$ git log --graph --oneline --all
https://i.imgur.com/buVF9GJ.png
撤消 Git 合并
$ git reset --hard HEAD~1
$ git log --graph --oneline --all
https://i.imgur.com/UDIUJ3c.png
您只能使用两个命令来恢复合并或通过特定提交重新启动:
git reset --hard commitHash (你应该使用你想要重新启动的提交,例如 44a587491e32eafa1638aca7738) git push origin HEAD --force (将新的本地 master 分支发送到 origin/master)
祝你好运,继续前进!
只是为了查看一个额外的选项,我一直主要遵循此处描述的分支模型:http://nvie.com/posts/a-successful-git-branching-model/,因此通常与 --no-ff
合并(没有快进)。
我刚刚阅读了这个页面,因为我不小心将一个测试分支而不是我的发布分支与用于部署的 master 合并(网站,master 是实时的)。测试分支合并了另外两个分支,总共大约有六个提交。
因此,要恢复整个提交,我只需要一个 git reset --hard HEAD^
就可以恢复整个合并。由于合并没有快进,因此合并是一个块,后退一步是“分支未合并”。
如果您的合并和相应的提交尚未推送,您可以随时切换到另一个分支,删除原始分支并重新创建它。
例如,我不小心将一个开发分支合并到 master 中并想撤消它。使用以下步骤:
git checkout develop
git branch -D master
git branch -t master origin/master
瞧! Master与origin处于同一阶段,并且您的错误合并状态被擦除。
如果您想要一个命令行解决方案,我建议您只使用 MBO 的答案。
如果您是新手,您可能会喜欢图形方法:
启动 gitk (从命令行,或在文件浏览器中右键单击,如果有的话)您可以轻松地在那里发现合并提交 - 从顶部开始的第一个节点,有两个父节点按照链接到第一个/左父节点(那个在合并之前的当前分支上,对我来说通常是红色的)在选定的提交上,右键单击“将分支重置到此处”,在那里选择硬重置
策略:创建一个新的分支,一切都很好。
理由:恢复合并很难。有太多的解决方案,这取决于许多因素,例如您是否已提交或推送您的合并,或者自合并后是否有新的提交。此外,您仍然需要对 git 有比较深入的了解才能使这些解决方案适应您的情况。如果你盲目地遵循一些说明,你最终可能会得到一个“空合并”,其中不会合并任何内容,进一步的合并尝试会让 Git 告诉你“已经是最新的”。
解决方案:
假设您要将 dev
合并到 feature-1
。
找到要接收合并的修订: git log --oneline feature-1 a1b2c3d4 Merge branch 'dev' into 'feature-1' <-- 要撤消的合并 e5f6g7h8 Fix NPE in the Zero Point Module <- - 合并之前的那个,你可能想要这个检查它(回到过去): git checkout e5f6g7h8 从那里创建一个新分支并检查它: git checkout -b feature-1
现在您可以重新开始合并:
合并: git merge dev 修复合并冲突。提交: git commit 对结果满意后,删除旧分支: git branch --delete feature-1
只需创建新分支,然后挑选所需的提交给它。
它的保护程序和简单的然后重置在上面的许多答案中描述
如果没有冲突和合并完成,则:
git reset --hard HEAD~1
如果在进行合并时发生冲突,则 abort 将使您退出最近的合并更改:
git merge --abort
我认为您可以执行 git rebase -i [hash] [branch_name]
,其中 [hash]
是您想要倒退多远的标识哈希加一(或您想要返回的许多提交),然后删除您在编辑器中提交的行不想要了。保存文件。出口。祈祷。它应该被重绕。您可能必须执行 git reset --hard
,但此时应该很好。如果您不想将它们保留在历史记录中,您也可以使用它从堆栈中提取特定提交,但这可能会使您的存储库处于您可能不想要的状态。
最简单的机会,比这里所说的要简单得多:
删除您的本地分支(本地,而不是远程)并再次拉取它。这样,您将撤消主分支上的更改,并且任何人都会受到您不想推送的更改的影响。重新开始。
如果您提交了合并:
git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard
首先,确保你已经承诺了一切。然后将您的存储库重置为之前的工作状态: $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 或使用 --hard (这将删除所有本地的,未提交的更改!): $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard 使用在错误合并提交之前存在的哈希. 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 ... 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在合并它们之前进行更改: git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f 其中这是您提交的正确提交的范围(不包括错误提交的合并)。
git log
选择默认显示的结果 - 可能有不同的git log
输出或git reflog
可用于此)git log
输出中,您想要查看两个父提交。一个是您分支中的最新提交,一个是您合并到的分支中的最新提交。您想要git reset --hard
到您合并到的分支上的父提交。git reset --hard <commit_sha>