Revert a merge after being pushed

GitGit Revert

Git Problem Overview


Steps I performed:

I have two branches branch1 and branch2,

$git branch --Initial state
$branch1

$git checkout branch2
$git pull origin branch1 --Step1

I resolve the conflicts and did a

$git commit -m "Merge resolved"

then

$git checkout branch1
$git merge branch2
$git push origin branch1

Now I realised that while being at step1, the auto merging removed some code and the change code was pushed. Now I want to go back to my initial state in order to revert any changes. Looking for some immediate help?

Git Solutions


Solution 1 - Git

You can revert the merge following the official guide, however this leaves Git with the erroneous belief that the merged commits are still on the target branch.

Basically you have to :

git revert -m 1 (Commit id of the merge commit)

Solution 2 - Git

Try using git reflog <branch> to find out where your branch was before the merge and git reset --hard <commit number> to restore the old revision.

Reflog will show you older states of the branch, so you can return it to any change set you like.

Make sure you are in correct branch when you use git reset

To change remote repository history, you can do git push -f, however this is not recommended because someone can alredy have downloaded changes, pushed by you.

Solution 3 - Git

The first option is the use of git revert.

git revert -m 1 [sha-commit-before-merge]

The git revert will revert the changes but will keep the history. Therefore you will not be able to continue working in the same branch since you cannot see the actual difference between the merged branch and your feature branch anymore. Use the following way to remove history as well. Do this very carefully if and only if you are the only one pushing changes to the branch at the moment.

git reset --hard [sha-commit-before-merge]
git push [origin] [branch] --force

Solution 4 - Git

In my case, I merged my branch (say: my-branch) with another feature branch (feature-branch) but not master. So my branch history was like this:

my-branch (before merge)

---master----m1----m2----m3---m4

After merging it with another feature-branch which had commits f1, f2 on top of master, it became like this:

my-branch (after merge)

---master----m1----m2----f1----f2----m3---m4----mergecommit

This might have happened because while working on my branch I did a merge from master after 2 commits, or one of 2 branches might not have been up to date with master. So in this case git revert -m 1 was not working as it was leaving those f1 and f2 commits in between.

The solution was simple, which will work in case of normal scenarios, where we don't have in-between commits:

git rebase -i HEAD~6

Instead of 6 use appropriate number based on how many past commits you want to change. Now Vim editor is opened, just mark undesired commits as drop and same and quit using :wq verify log:

git log --oneline 

force push

git push -f

Now the remote branch should be in previous state.

Solution 5 - Git

As mentioned in another answer, the primary issue with doing a git revert on a merge is that git still thinks all the previous commits were merged (it only changes the code). If you attempt to merge that branch later on, you'll find those prior commits are missing.

The better way (obviously after consulting with your team so they don't keep working on a problematic branch) is to git reset to an earlier commit. It doesn't have to be a hard reset, since that only deals with what to do with your current working changes, so that part is up to you.

You can also create a temporary branch from the previous commit if you would like to make changes there first before doing the reset. In that case you would reset to a commit on your temporary branch.

You won't be able to push without pulling from your upstream, but obviously you don't want to pull the changes you're trying to revert. So, you'll need to do a force push (or force push with lease to stop if any changes have been pushed in the interim).

Side Note: As a fan of VS Code and Git Graph, I find the force push is easy to do by right clicking on the local branch tag name and selecting 'Push Branch...', choosing either Force or Force With Lease, leaving the Set Upstream box checked.

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
QuestionBijendraView Question on Stackoverflow
Solution 1 - GitalerootView Answer on Stackoverflow
Solution 2 - GitIlya IvanovView Answer on Stackoverflow
Solution 3 - GitAsanka sanjayaView Answer on Stackoverflow
Solution 4 - GitRahul R.View Answer on Stackoverflow
Solution 5 - GitRegular UserView Answer on Stackoverflow