The Problem
Here’s the scenario:
I had a git repo that looks like this:
A-B---- master
\ /
C-D *develop
I was on the develop
branch. Here’s the foolish thing that I did:
- I forgot that
develop
differed from themaster
branch, - Made a change on
develop
, committed it, and merged it intomaster
, and - Pushed the change to my remote (called
publish
).
There were no changes after B
on the master
branch, and as such, when I merge
d, git did a fast-forward. My repo now looked like this:
A-B-C-D master, develop, remotes/publish/master, remotes/publish/develop.
I wanted to keep develop
at D
, but revert master
to B
, and then merge the changes made at D
into master
.
What I Should’ve Done to Start With
What I should’ve done was:
git checkout master #change to `master` branch
git checkout -b hotfix #make a new branch called `hotfix` from `master`
#make file changes
git commit #commit the `hotfix`
git checkout master #switch back to `master`
git merge hotfix #pull in the hotfix changes
git checkout develop #switch to `develop`
git merge hotfix #pull in the hotfix changes
git push publish #push everything to my remote.
Resulting in a diagram that looks like this:
D-- hotfix
/ \
A-B---- E master
\ |
C---F *develop
Fixing the Mistake
Turns out the solution wasn’t really that hard, but git can be really scary if you’re not sure what you’re doing. The develop
branch is already in the right spot, so we just need to:
# Make sure we're on the `master` branch
git checkout master
# Move `master` back to revision `B`, deleting all other changes in the working
# directory.
git reset --hard sha-of-B
# Because we've reverted some changes, we need to force the remote to accept the
# reversion.
git push publish --force
That reverts the master
branch back before the merge. To then pull in the changes made in the hotfix:
git cherry-pick sha-of-D #pull in only the changes made in revision D.
git push publish
And we’re done!
Thanks to Simon Boudrias for his help on this one. See the StackOverflow question here.