Tag Cloud

Absorbing Changes into a Commit Series with Mercurial

Imagine this scenario. You've pushed a large series of commits to your favourite review tool
(because you are a believer in the glory of microcommits). The reviewer however has found several
problems, and worse, they are spread across all of the commits in your series. How do you fix all
the issues with minimal fuss while preserving the commit order?

If you were using the builtin histedit extension, you might make temporary "fixup" commits for
each commit that had issues. Then after running hg histedit you'd roll them up into their
respective parent. Or if you were using the evolve extension (which I definitely recommend),
you might do something like this:

Both methods are serviceable, but involve some jumping around through hoops to accomplish. Enter a
new extension from Facebook called absorb. The absorb extension will take each change in your
working directory, figure out which commits in your series modified that line, and automatically
amend the change to that commit. If there is any ambiguity (i.e multiple commits modified the same
line), then absorb will simply ignore that change and leave it in your working directory to be
resolved manually. So instead of the rather convoluted processes above, you can do this:

# fix all issues across all commits$ hg absorb

It's magic!

Installing Absorb

There's one big problem. The docs in the hg-experimental repo (where absorb lives) are
practically non-existent, and installation is a bit of a pain. So here are the steps I took to get
it working on Fedora. They won't hand hold you for other platforms, but they should at least point
you in the right direction.

First, clone the hg-experimental repo:

$ hg clone https://bitbucket.org/facebook/hg-experimental

Absorb depends on a compiled python module called linelog which also lives in hg-experimental.
In order to compile linelog, you'll need some dependencies:

$ sudo pip install cython
$ sudo dnf install python-devel

Edit: Previously I had lz4-devel and openssl-devel listed as dependencies, but as junw notes, that's only needed if you are compiling the whole hg-experimental repo (by omitting the --component flag below). Though it looks like lz4 might still be needed on OSX.

Make sure the cython dependency gets installed to the same python your mercurial install uses.
That may mean dropping the sudo from the pip command if you have mercurial running in user space.
Next, compile the hg-experimental repo by running: