Undo a fast-forward merge
GitGit Problem Overview
I've made some changes to my git repo that I wish to undo.
My git repo looked like this:
A-B---- master
\ /
C-D * develop
I was on the develop
branch, forgot that it differed from the master
branch, made a change on develop
, merged it into master
, and then pushed to my remote (called publish
).
Because there were no changes on master since B (common ancestor), git did a fast-forward merge.
Now, my repo looks like this:
A-B-C-D master, develop, remotes/publish/master, remotes/publish/develop.
I wanted to revert the last merge, restoring master
to B.
From what I read in https://stackoverflow.com/questions/927358/undo-last-git-commit, I used git reset sha-of-B
to restore my master
branch to revision B.
Questions:
- How do I restore
develop
to revision D? - How do I then push these changes back to remote/publish?
Git Solutions
Solution 1 - Git
If you reset the branch master, it won't touch develop branch. In order to reput all in order, you should do:
git checkout master
git reset --hard sha-of-B
git checkout develop
git reset --hard sha-of-D
git checkout master
git merge develop --no-ff
Solution 2 - Git
- imagine you are still on master where you merged and pushed
git reset --hard @{1}
- this resets branch “master” to where it was one step back on your computer (i.e. at “B”)
- for develop do nothing, because it should still be at “D”
git push publish develop
- this pushes branch “develop” in the usual way
git push publish master --force-with-lease
- pushes branch “master” backwards, with the permission gained via
--force-with-lease
in a safe way - the use of
--force
might silently overwrite work from others, so I never use that
- pushes branch “master” backwards, with the permission gained via
- or both push operations together with this surprising syntax:
git push publish develop --force-with-lease=master
Solution 3 - Git
If seems that you were checked out to develop
when you ran git reset
, and this is what messed you up.
You can fix develop
as follows:
git checkout develop
git merge --ff-only D
Now, you can restore master
back to B:
git checkout master
git reset --hard B
Get back to develop
and push it:
git checkout develop
git push develop