How to revert a merge commit that's already pushed to remote branch?

Git

Git Problem Overview


git revert <commit_hash> alone won't work. -m must be specified, and I'm pretty confused about it.

Anyone experienced this before?

Git Solutions


Solution 1 - Git

The -m option specifies the parent number. This is because a merge commit has more than one parent, and Git does not know automatically which parent was the mainline, and which parent was the branch you want to un-merge.

When you view a merge commit in the output of git log, you will see its parents listed on the line that begins with Merge:

commit 8f937c683929b08379097828c8a04350b9b8e183
Merge: 8989ee0 7c6b236
Author: Ben James <ben@example.com>
Date:   Wed Aug 17 22:49:41 2011 +0100

Merge branch 'gh-pages'

Conflicts:
    README

In this situation, git revert 8f937c6 -m 1 will get you the tree as it was in 8989ee0, and git revert -m 2 will reinstate the tree as it was in 7c6b236.

To better understand the parent IDs, you can run:

git log 8989ee0 

and

git log 7c6b236

Solution 2 - Git

Here's a complete example in the hope that it helps someone:

git revert -m 1 <commit-hash> 
git push -u origin master

Where <commit-hash> is the commit hash of the merge that you would like to revert, and as stated in the explanation of this answer, -m 1 indicates that you'd like to revert to the tree of the first parent prior to the merge.

The git revert ... line essentially commits your changes while the second line makes your changes public by pushing them to the remote branch.

Solution 3 - Git

Ben has told you how to revert a merge commit, but it's very important you realize that in doing so

> "...declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge. This may or may not be what you want." (git-merge man page).

An article/mailing list message linked from the man page details the mechanisms and considerations that are involved. Just make sure you understand that if you revert the merge commit, you can't just merge the branch again later and expect the same changes to come back.

Solution 4 - Git

You could follow these steps to revert the incorrect commit(s) or to reset your remote branch back to correct HEAD/state.

> Note: Apply this solution only for your own branch, not for a shared > branch.

  1. checkout the remote branch to local repo.
    git checkout your_branch_name
  2. copy the commit hash (i.e. id of the commit immediately before the wrong commit) from git log git log -n5

should show something like this: > commit 7cd42475d6f95f5896b6f02e902efab0b70e8038 "Merge branch > 'wrong-commit' into 'your_branch_name'"
commit > f9a734f8f44b0b37ccea769b9a2fd774c0f0c012 "this is a wrong commit" > commit 3779ab50e72908da92d2cfcd72256d7a09f446ba "this is the correct > commit"

  1. reset the branch to the commit hash copied in the previous step
    git reset <commit-hash> (i.e. 3779ab50e72908da92d2cfcd72256d7a09f446ba)
  2. run the git status to show all the changes that were part of the wrong commit.
  3. simply run git reset --hard to revert all those changes.
  4. force-push your local branch to remote and notice that your commit history is clean as it was before it got polluted.
    git push -f origin your_branch_name

Solution 5 - Git

git revert -m 1 <merge-commit>

Solution 6 - Git

To keep the log clean as nothing happened (with some downsides with this approach (due to push -f)):

git checkout <branch>
git reset --hard <commit-hash-before-merge>
git push -f origin HEAD:<remote-branch>

'commit-hash-before-merge' comes from the log (git log) after merge.

Solution 7 - Git

All the answers already covered most of the things but I will add my 5 cents. In short reverting a merge commit is quite simple:

git revert -m 1 <commit-hash>

If you have permission you can push it directly to the "master" branch otherwise simply push it to your "revert" branch and create pull request.

You might find more useful info on this subject here: https://itcodehub.blogspot.com/2019/06/how-to-revert-merge-in-git.html

Solution 8 - Git

Sometimes the most effective way to rollback is to step back and replace.

git log

Use the 2nd commit hash (full hash, the one you want to revert back to, before the mistake listed) and then rebranch from there.

git checkout -b newbranch <HASH>

Then delete the old branch, copy the newbranch over in its place and restart from there.

git branch -D oldbranch
git checkout -b oldbranch newbranch

If its been broadcast, then delete the old branch from all repositories, push the redone branch to the most central, and pull it back down to all.

Solution 9 - Git

If you want to revert a merge commit, here is what you have to do.

  1. First, check the git log to find your merge commit's id. You'll also find multiple parent ids associated with the merge (see image below).

enter image description here

Note down the merge commit id shown in yellow. The parent IDs are the ones written in the next line as Merge: parent1 parent2. Now...

Short Story:

  1. Switch to branch on which the merge was made. Then Just do the git revert <merge commit id> -m 1 which will open a vi console for entering commit message. Write, save, exit, done!

Long story:

  1. Switch to branch on which the merge was made. In my case, it is the test branch and I'm trying to remove the feature/analytics-v3 branch from it.

  2. git revert is the command which reverts any commit. But there is a nasty trick when reverting a merge commit. You need to enter the -m flag otherwise it will fail. From here on, you need to decide whether you want to revert your branch and make it look like exactly it was on parent1 or parent2 via:

git revert <merge commit id> -m 1 (reverts to parent2)

git revert <merge commit id> -m 2 (reverts to parent1)

You can git log these parents to figure out which way you want to go and that's the root of all the confusion.

Solution 10 - Git

I found good explanation for How To Revert The Merge from this link and I copy pasted the explanation below and it would be helpful just in case if below link doesn't work.

How to revert a faulty merge Alan([email protected]) said:

I have a master branch. We have a branch off of that that some developers are doing work on. They claim it is ready. We merge it into the master branch. It breaks something so we revert the merge. They make changes to the code. they get it to a point where they say it is ok and we merge again. When examined, we find that code changes made before the revert are not in the master branch, but code changes after are in the master branch. and asked for help recovering from this situation.

The history immediately after the "revert of the merge" would look like this:

---o---o---o---M---x---x---W
              /
      ---A---B

where A and B are on the side development that was not so good, M is the merge that brings these premature changes into the mainline, x are changes unrelated to what the side branch did and already made on the mainline, and W is the "revert of the merge M" (doesn’t W look M upside down?). IOW, "diff W^..W" is similar to "diff -R M^..M".

Such a "revert" of a merge can be made with:

$ git revert -m 1 M After the developers of the side branch fix their mistakes, the history may look like this:

---o---o---o---M---x---x---W---x
              /
      ---A---B-------------------C---D

where C and D are to fix what was broken in A and B, and you may already have some other changes on the mainline after W.

If you merge the updated side branch (with D at its tip), none of the changes made in A or B will be in the result, because they were reverted by W. That is what Alan saw.

Linus explains the situation:

Reverting a regular commit just effectively undoes what that commit did, and is fairly straightforward. But reverting a merge commit also undoes the data that the commit changed, but it does absolutely nothing to the effects on history that the merge had. So the merge will still exist, and it will still be seen as joining the two branches together, and future merges will see that merge as the last shared state - and the revert that reverted the merge brought in will not affect that at all. So a "revert" undoes the data changes, but it's very much not an "undo" in the sense that it doesn't undo the effects of a commit on the repository history. So if you think of "revert" as "undo", then you're going to always miss this part of reverts. Yes, it undoes the data, but no, it doesn't undo history. In such a situation, you would want to first revert the previous revert, which would make the history look like this:

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

where Y is the revert of W. Such a "revert of the revert" can be done with:

$ git revert W This history would (ignoring possible conflicts between what W and W..Y changed) be equivalent to not having W or Y at all in the history:

---o---o---o---M---x---x-------x----
              /
      ---A---B-------------------C---D

and merging the side branch again will not have conflict arising from an earlier revert and revert of the revert.

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

Of course the changes made in C and D still can conflict with what was done by any of the x, but that is just a normal merge conflict.

Solution 11 - Git

When you view a merge commit in the output of git log, you will see its parents listed on the line that begins with Merge:

commit 8f937c683929b08379097828c8a04350b9b8e183
Merge: 8989ee0 7c6b236
Author: Ben James <ben@example.com>
Date:   Wed Aug 17 22:49:41 2011 +0100

Merge branch 'gh-pages'

Conflicts:
    README

In this situation, git revert 8f937c6 -m 1 will get you the tree as it was in 8989ee0, and git revert -m 2 will reinstate the tree as it was in 7c6b236.

To better understand the parent IDs, you can run:

git log 8989ee0 

and

git log 7c6b236

Take a backup branch

git checkout -b mybackup-brach

git reset --hard 8989ee0 
git push origin -u mybackup-branch

So now you have the changes before the merge, If everything Okay, checkout into previous branch and reset with backup branch

git reset --hard origin/mybakcup-branhc

Solution 12 - Git

The correctly marked answer worked for me but I had to spend some time to determine whats going on.. So I decided to add an answer with simple straightforward steps for cases like mine..

Lets say we got branches A and B.. You merged branch A into branch B and pushed branch B to itself so now the merge is part of it.. But you want to go back to the last commit before the merge.. What do you do?

  1. Go to your git root folder (the project folder usually) and use git log
  2. You will see the history of recent commits - the commits have commit/author/date properties while the merges also have a merge property - so you see them like this:

commit: <commitHash> Merge: <parentHashA> <parentHashB> Author: <author> Date: <date>

  1. Use git log <parentHashA> and git log <parentHashB> - you will see the commit histories of those parent branches - the first commits in the list are the latest ones
  2. Take the <commitHash> of the commit you want, go to your git root folder and use git checkout -b <newBranchName> <commitHash> - that will create a new branch starting from that last commit you've chosen before the merge.. Voila, ready!

Solution 13 - Git

This is a very old thread, but I am missing another in my opinion convenient solution:

I never revert a merge. I just create another branch from the revision where everything was ok and then cherry pick everything that needs to picked from the old branch which was added in between.

So, if the GIT history is like this:

  • d
  • c
  • b <<< the merge
  • a
  • ...

I create a new branch from a, cherry pick c and d and then the new branch is clear from b. I can ever decide to do the merge of "b" in my new branch again. The old branch becomes deprecated and will be deleted if "b" is not necessary anymore or still in another (feature/hotfix) branch.

The only problem is now one of the very hardest things in computer science: How do you name the new branch? ;)

Ok, if you failed esp. in devel, you create newdevel as mentioned above, delete old devel and rename newdevel to devel. Mission accomplished. You can now merge the changes again when you want. It is like never merged before....

Solution 14 - Git

A very simple answer if you are looking to revert the change that you pushed just now :

commit 446sjb1uznnmaownlaybiosqwbs278q87
Merge: 123jshc 90asaf


git revert -m 2 446sjb1uznnmaownlaybiosqwbs278q87 //does the work

Solution 15 - Git

I found creating a reverse patch between two know end-points and applying that patch would work. This presumes that you have created snapshots (tags) off of your master branch or even a back up of your master branch say master_bk_01012017.

Say the code branch you merged into master was mycodebranch.

  1. Checkout master.
  2. Create a full binary reverse patch between master and your backup. git diff --binary master..master_bk_01012017 > ~/myrevert.patch
  3. Check your patch
    git apply --check myrevert.patch
  4. Apply patch with sign-off
    git am --signoff < myrevert.patch
  5. If you will need to bring in this code again once it is fixed, you will need to branch off the reverted master and checkout the fix branch
    git branch mycodebranch_fix
    git checkout mycodebranch_fix
  6. Here you need to find the SHA key for the revert and revert the revert git revert [SHA]
  7. Now you can use your mycodebranch_fix to fix the issues, commit and re-merge into master once done.

Solution 16 - Git

git doc about git revert -m provide a link exactly explain this: https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt

Solution 17 - Git

-m1 is the last parent of the current branch that is being fixed, -m 2 is the original parent of the branch that got merged into this.

Tortoise Git can also help here if command line is confusing.

Solution 18 - Git

I also faced this issue on a PR that has been merged to the master branch of a GitHub repo.

Since I just wanted to modify some modified files but not the whole changes the PR brought, I had to amend the merge commit with git commit --am.

Steps:

  1. Go to the branch which you want to change / revert some modified files
  2. Do the changes you want according to modified files
  3. run git add * or git add <file>
  4. run git commit --am and validate
  5. run git push -f

Why it's interesting:

  • It keeps the PR's author commit unchanged
  • It doesn't break the git tree
  • You'll be marked as committer (merge commit author will remain unchanged)
  • Git act as if you resolved conflicts, it will remove / change the code in modified files as if you manually tell GitHub to not merge it as-is

Solution 19 - Git

As Ryan mentioned, git revert could make merging difficult down the road, so git revert may not be what you want. I found that using the git reset --hard <commit-hash-prior-to-merge> command to be more useful here.

Once you have done the hard reset part, you can then force push to the remote branch, i.e. git push -f <remote-name> <remote-branch-name>, where <remote-name> is often named origin. From that point you can re-merge if you'd like.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYazView Question on Stackoverflow
Solution 1 - GitBen JamesView Answer on Stackoverflow
Solution 2 - GitSaheedView Answer on Stackoverflow
Solution 3 - GitRyan StewartView Answer on Stackoverflow
Solution 4 - GitssasiView Answer on Stackoverflow
Solution 5 - GitNeeraj KumarView Answer on Stackoverflow
Solution 6 - GitnvdView Answer on Stackoverflow
Solution 7 - GitxprophView Answer on Stackoverflow
Solution 8 - Gitppostma1View Answer on Stackoverflow
Solution 9 - Gitsaran3hView Answer on Stackoverflow
Solution 10 - GitMK446View Answer on Stackoverflow
Solution 11 - GitAnilSView Answer on Stackoverflow
Solution 12 - GitБожидар ЙовчевView Answer on Stackoverflow
Solution 13 - GitmiwoeView Answer on Stackoverflow
Solution 14 - GitarqamView Answer on Stackoverflow
Solution 15 - GitalexplainView Answer on Stackoverflow
Solution 16 - GitJunyongView Answer on Stackoverflow
Solution 17 - GitVinayView Answer on Stackoverflow
Solution 18 - GitMaxime LafarieView Answer on Stackoverflow
Solution 19 - GitHarry WangView Answer on Stackoverflow