Zen and the Art of Git Chainsaw Maintenance
Git is pretty awesome and mind expanding, but I don’t think that anything is quite a mind-blowing as the first time you learn how to revert a merge. There’s a great explanation here: http://stackoverflow.com/questions/1078146/re-doing-a-reverted-merge-in-git
Basically, if you’ve merged a feature in by mistake, you can simply revert the merge to get back to a happy state. The mind bending comes when you decide that the feature is ready to be merged for real. While intuition might tell you to just git merge feature again, what you really want to do is “revert the revert”.
It makes sense, and it’s awesome, and it’s righteously scary in that wonderful way that only git can be.
At PatientsLikeMe we were familiar with this, but we hadn’t had a chance to do it in practice until last week. A branch was merged in prematurely and we successfully reverted.
The new wrinkle that I faced today was that the branch that was merged in and since reverted, is actually a long running branch and development continues on it. I wanted to merge master into this long running branch to stay up to date, but when I did that, I noticed pretty quickly that something was awry. 27 conflicts and a bucket of fail. Worse, my mergetool was consistently picking the wrong side of the merge.
Let’s go to the simulated instant replay, sponsored by GitX.
This is the state of the repo after we’re reverted our accidental merge.
Here is the repo with more work on both the feature and the master branch.
So, I’d like to merge master into the feature branch, but that leads to a sorts of erroneous conflicts. Why? Well, because git merge master asks git to merge the revert commit into my feature branch, that’s why. The revert commit essentially contains diffs that say to remove all the early work on feature branch.
It makes sense to apply this to master, but it is a terrible commit to apply to the feature branch. It’s a bit like time travelling and accidentally killing your parents.
So what do we do? We know that we need to ‘revert the revert’ at some point. It turns out that there’s no reason not to do that immediately; we just need a new ‘shim’ branch. We’ll call it master_w_revert_reverted.
git checkout master git checkout -b master_w_revert_reverted git revert SHA_OF_THE_MERGE_REVERSION git commit
Now let's merge this shim into our feature branch.
git co feature git merge master_w_revert_reverted
Voila! we’ve successfully merged our master branch into the long running feature and we’ve taken care of the ‘revert the revert’ going forward.
The next time we want to merge from master to the long running feature branch, or indeed from when we’re ready to merge the feature into master, we just merge as we would normally. Our days of reversion are over.
Until next time, happy merging!