撤消尚未推送的Git合并

时间:2010-03-05 19:24:45

标签: git undo git-merge

在我的主分支中,我在本地执行了git merge some-other-branch,但从未将更改推送到原始主服务器。我不是故意合并,所以我想撤消它。合并后执行git status时,我收到此消息:

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

根据一些instructions I found,我尝试了

git revert HEAD -m 1

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

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

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

32 个答案:

答案 0 :(得分:3823)

使用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
  

- 合并

     

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

答案 1 :(得分:1356)

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

git reset --hard origin/master

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

答案 2 :(得分:1122)

请参阅chapter 4 in the Git bookthe original post by Linus Torvalds

撤消已推送的合并

git revert -m 1 commit_hash

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

答案 3 :(得分:924)

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

git reset --merge ORIG_HEAD

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

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

答案 4 :(得分:349)

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

git merge --abort

来自man git merge

  

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

答案 5 :(得分:119)

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

git reset --hard HEAD^

甚至HEAD^^还原该还原提交。如果您不确定应该采取多少步骤,则可以随时提供完整的SHA参考。

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

答案 6 :(得分:81)

最近,我一直在使用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强制这个分支在合并之前进行跟踪,并随身携带。

答案 7 :(得分:47)

使用现代Git,您可以:

git merge --abort

旧语法:

git reset --merge

老派:

git reset --hard

但实际上,值得注意的是git merge --abort仅等同于git reset --merge,因为MERGE_HEAD存在。这可以在Git help for merge命令中读取。

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在日常工作中更加强大和有用,所以这就是我一直使用的那个。

答案 8 :(得分:36)

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

这样做......

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

答案 9 :(得分:21)

您可以使用git reflog查找之前的结帐。有时这是一个你想要回归的好状态。

具体地,

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

答案 10 :(得分:13)

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

$ git checkout -f

它将撤消合并(以及你所做的一切)。

答案 11 :(得分:13)

得到这个问题也希望恢复到匹配原点(即,NO在原点之前提交)。进一步研究,发现有一个reset命令正是如此:

git reset --hard @{u}

注意:@{u}origin/master的简写。 (当然,您需要该远程存储库才能实现此目的。)

答案 12 :(得分:11)

我能够使用一个不涉及查找提交ID的命令来解决此问题。

<xsl:template match="*[contains(name(), 'Parent')]">
    <xsl:copy>
        <xsl:attribute name="childattribute">
            <xsl:value-of select="1" />
        </xsl:attribute>
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>

接受的答案对我不起作用,但是此命令达到了我想要的结果。

答案 13 :(得分:10)

只是为了看一个额外的选项,我一直主要关注这里描述的分支模型:http://nvie.com/posts/a-successful-git-branching-model/因此通常与--no-ff(没有快进)合并。

我刚看完这个页面,因为我意外地合并了一个测试分支而不是我的发布分支与master进行部署(网站,主是什么是现场)。测试分支有两个其他分支合并到它,总共约六个提交。

因此,要恢复整个提交,我只需要一个git reset --hard HEAD^并恢复整个合并。由于合并没有快速转发,合并是一个块,后退一步是“分支未合并”。

答案 14 :(得分:10)

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

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

答案 15 :(得分:10)

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

答案 16 :(得分:10)

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

首先做git reset --merge ORIG_HEAD

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

git push origin HEAD --force

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

答案 17 :(得分:8)

您必须更改自己的HEAD,当然不是git HEAD。...

因此,在回答之前,让我们添加一些背景知识,解释一下这是什么HEAD

First of all what is HEAD?

HEAD只是对当前分支上当前提交(最新)的引用。
在任何给定时间只能有一个HEAD。 (不包括git worktree

HEAD的内容存储在.git/HEAD内部,并且包含当前提交的40个字节的SHA-1。


detached HEAD

如果您不在最近的提交上,则意味着HEAD指向历史上的先前提交,称为 detached HEAD 。< / p>

enter image description here

在命令行上,它看起来像这样-SHA-1而不是分支名称,因为HEAD没有指向当前分支的尖端

enter image description here

enter image description here

关于如何从分离的HEAD中恢复的几种选择:


git checkout

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@{...}

这将使您回到所需的提交

enter image description here


git reset --hard <commit_id>

“将” 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.
  • 注意:(Since Git 2.7
    您也可以使用git rebase --no-autostash

git revert <sha-1>

“撤消”给定的提交或提交范围。
reset命令将“撤消”在给定提交中所做的任何更改。
带有撤消补丁的新提交将被提交,而原始提交也将保留在历史记录中。

# 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

enter image description here

答案 18 :(得分:7)

如果您的合并和相应的提交尚未推送,您可以随时切换到另一个分支,删除原始分支并重新创建。

例如,我意外地将开发分支合并到主分支中并想要撤消它。使用以下步骤:

git checkout develop
git branch -D master
git branch -t master origin/master

瞧!师父与原籍处于同一阶段,你的错误合并状态将被删除。

答案 19 :(得分:4)

如果你想要一个命令行解决方案,我建议你选择MBO的答案。

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

  1. 启动gitk(从命令行开始,或者如果有的话,右键单击文件浏览器)
  2. 您可以轻松地发现合并提交 - 顶部的第一个节点有两个父母
  3. 点击第一个/左父母的链接(合并前当前分支上的那个,通常是红色)
  4. 在选定的提交中,右键单击“将分支重置为此处”,然后选择硬重置

答案 20 :(得分:4)

策略:从一切都很好的地方创建一个新分支。

理由:恢复合并很难。解决方案太多,取决于许多因素,例如您是否已提交或推送合并,或者自您合并后是否有新提交。此外,您仍然需要对git有一个相对深入的了解,以使这些解决方案适应您的情况。如果你盲目地遵循一些指示,你最终会得到一个空的合并&#34;什么都不会合并,进一步的合并尝试将使Git告诉你&#34;已经是最新的&#34;。

<强>解决方案:

我们假设您要将dev合并到feature-1

  1. 找到您要接收合并的修订:

    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. 检查出来(回到过去):

    git checkout e5f6g7h8
    
  3. 从那里创建一个新的分支并检查出来:

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

    1. 合并:git merge dev

    2. 修复合并冲突。

    3. 提交:git commit

    4. 如果您对结果感到满意,请删除旧分支:git branch --delete feature-1

答案 21 :(得分:3)

如果分支被清除而不被推送。然后,下面的git reset命令将撤消合并: git reset --merge ORIG_HEAD

答案 22 :(得分:1)

如果您提交了合并:

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

答案 23 :(得分:1)

  1. 首先,请确保您已经承诺了所有内容。

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

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

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

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

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

  3. 通过以下方式检查您要在之前正确版本的顶部重新提交哪些提交:

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  4. 通过以下方式在您的存储库的正确版本顶部应用您的权利提交:

    • 使用cherry-pick(某些现有提交引入的更改)

          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
      
    • 或者通过以下方式挑选提交范围:

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

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

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

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

答案 24 :(得分:0)

在这种情况下,您需要使用git reset --hard <branch_name>重置分支。如果要在重置之前保存更改,请务必创建新分支并git checkout <branch_name>

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

如果已推送更改,则可以使用git revert <branch_name>代替。请务必查看如何在其他方案中使用git revert and git checkout

答案 25 :(得分:0)

最简单的机会,比这里所说的更简单:

删除您的本地分支(本地分支,而不是远程分支)并再次将其拉出。这样您就可以撤消主分支上的更改,任何人都会受到您不想推送的更改的影响。重新开始。

答案 26 :(得分:0)

如果您发现需要在合并后立即恢复,并且在合并尝试后仍未执行任何其他操作,则可以发出以下命令: git reset --hard HEAD@{1}

基本上,如果合并后没有提交任何其他内容,那么合并sha将指向HEAD@{0},因此HEAD@{1}将是合并之前的前一个点。

答案 27 :(得分:0)

  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

这对我有用.. !!

答案 28 :(得分:0)

可以通过多种方式完成。

1)中止合并

如果您处于合并错误(错误地用错误的分支完成)之间,并且想要避免合并,请返回到最新的分支,如下所示:

page = driver.get("https://www.memrise.com/course/2021573/french-1-145/garden/speed_review/?source_element=ms_mode&source_screen=eos_ms")
page = requests.get("https://www.memrise.com/course/2021573/french-1-145/garden/speed_review/?source_element=ms_mode&source_screen=eos_ms")
element = driver.find_element_by_link_text('Log in with Google')
element.click()
soup = BeautifulSoup(page.content, 'html.parser')
while True:
    front_half = soup.find_all(id='prompt-row')
    print(front_half)
    time.sleep(1)

2)将HEAD重置为远程分支

如果您是从远程开发分支工作,则可以将HEAD重置为远程分支上的最后一次提交,如下所示:

git merge --abort

3)删除当前分支,然后再次从远程存储库中签出

考虑到,您正在本地仓库中开发developer分支,该分支与远程/ develop分支同步,您可以执行以下操作:

git reset --hard origin/develop

答案 29 :(得分:0)

只需创建一个新分支,然后将所需的提交樱桃挑选即可。

它的保护程序更加简单,然后重置,如上面许多答案所述

答案 30 :(得分:0)

回答问题“ 撤消尚未推送的Git合并

您可以使用git reset --hard HEAD~1

请考虑以下情况,其中有两个分支 master feature-1


$ git log --graph --oneline --all

进行Git合并

$ git merge feature-1

$ git log --graph --oneline --all

撤消Git合并

$ git reset --hard HEAD~1

$ git log --graph --oneline --all

答案 31 :(得分:-13)

您可以使用git-reset命令。

  

git-reset - 将当前HEAD重置为

     

指定状态。 git reset [--mixed |

     

- 柔软| - 硬| --merge] [-q] [] git reset [-q] []

     

[ - ] ... git reset --patch

     

[] [ - ] [...]

GIT-Reset