Fun with Git: Revert Revert

15 August 2017

Git revert is a feature that allows to cancel changes, introduced by a commit by creating a new commit with exactly opposite diff. Handy enough, but sometimes a problem could arise.

First of all, creating a new commit is a good thing. It makes history transparent and auditable. Unlike rebase, revert doesn’t mess with other’s people work.

But revert does introduce a new commit, which is a perfectly legit and oridinary one. Meaning, if you later want to rebase or merge master back into your branch, you’ll get some unexpected (at the first glance) results.

       P  Q       R S     
      /    \       / \
  A  B  C   D  D' E   F

D is a merge commit, D' is it’s revert-commit. R fixes something, E represents cumulative changes of the original branch after revert, which, probably, makes S merge-commit a reasonable thing.

This commit, S, is going to be troublesome. See, D', as I said is an ordinary commit, which deletes changes, introduced by P and Q (if the very same thing isn’t changed in R).

One possible solution is as follows.

       P  Q       R  / \ S 
      /    \       /     \
  A  B  C   D  D' E        F

In the new temporary branch make a revert commit D’’ of a revert commit D’, which, basically, means to reapply merge commit D to the new state of original branch. Then, merge it into the fixed working branch (S). This way, reverted changes would not be applied to the working branch and no work in progress would be deleted because of revert-commit D'.