Undo a Git merge that hasn't been pushed yet

2018-12-31 03:48发布

Within my master branch, I did a git merge some-other-branch locally, but never pushed the changes to origin master. I didn't mean to merge, so I'd like to undo it. When doing a git status after my merge, I was getting this message:

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

Based upon some instructions I found, I tried running

git revert HEAD -m 1

but now I'm getting this message with git status:

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

I don't want my branch to be ahead by any number of commits. How do I get back to that point?

27条回答
柔情千种
2楼-- · 2018-12-31 04:13

Strategy: Create a new branch from where everything was good.

Rationale: Reverting a merge is hard. There are too many solutions, depending on many factors such as whether you've committed or pushed your merge or if there were new commits since your merge. Also you still need to have a relatively deep understanding of git to adapt these solutions to your case. If you blindly follow some instructions, you can end up with an "empty merge" where nothing will be merged, and further merge attempts will make Git tell you "Already up to date".

Solution:

Let's say you want to merge dev into 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
    

Now you can restart your merge:

  1. Merge: git merge dev

  2. Fix your merge conflicts.

  3. Commit: git commit

  4. When you're satisfied with the results, delete the old branch: git branch --delete feature-1

查看更多
后来的你喜欢了谁
3楼-- · 2018-12-31 04:15

With git reflog check which commit is one prior the merge (git reflog will be a better option than git log). Then you can reset it using:

git reset --hard commit_sha

There's also another way:

git reset --hard HEAD~1

It will get you back 1 commit.

Be aware that any modified and uncommitted/unstashed files will be reset to their unmodified state. To keep them either stash changes away or see --merge option below.


As @Velmont suggested below in his answer, in this direct case using:

git reset --hard ORIG_HEAD

might yield better results, as it should preserve your changes. ORIG_HEAD will point to a commit directly before merge has occurred, so you don't have to hunt for it yourself.


A further tip is to use the --merge switch instead of --hard since it doesn't reset files unnecessarily:

git reset --merge ORIG_HEAD

--merge

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

查看更多
何处买醉
4楼-- · 2018-12-31 04:15

In this case, you will want to reset your branch with git reset --hard <branch_name>. If you want to save your changes before reseting them be sure to create a new branch and git checkout <branch_name>.

You can reset the state to a specific commit with git reset --hard <commit_id> as well.

If the changes have been pushed you can use git revert <branch_name> instead. Be sure to check out how to use git revert and git checkout in other scenarios as well.

查看更多
浮光初槿花落
5楼-- · 2018-12-31 04:16

I was able to resolve this problem with a single command that doesn't involve looking up a commit id.

git reset --hard remotes/origin/HEAD

The accepted answer didn't work for me but this command achieved the results I was looking for.

查看更多
回忆,回不去的记忆
6楼-- · 2018-12-31 04:17

If you notice that you need to revert immediately after the merge and you haven't done anything else after the merge attempt, you can just issue this command: git reset --hard HEAD@{1}.

Essentially, your merge sha will be pointing to HEAD@{0} if nothing else was committed after the merge and so HEAD@{1} will be the previous point before the merge.

查看更多
与君花间醉酒
7楼-- · 2018-12-31 04:19

See chapter 4 in the Git book and the original post by Linus Torvalds.

To undo a merge that was already pushed:

git revert -m 1 commit_hash

Be sure to revert the revert if you're committing the branch again, like Linus said.

查看更多
登录 后发表回答