NOTE: You almost certainly don’t want to do anything in this article. I wrote this in 2008; Mercurial has improved a lot since then. While everything’s still accurate (as far as I know), using MQ is pain-ridden and unnecessary. Instead, you should use histedit (which is bundled with Mercurial) or the evolve extension (which is not yet, but may be soon). Either will get you to the same place, but they’re both easier, safer, and more powerful than MQ—a rare triple. That said, if you’re curious how things used to work, or if you can’t use a modern version of Mercurial, read on.

Last night, I realized that I had accidentally made some commits to one of my Mercurial repositories without an email address set, meaning that they all showed up as benjamin@localhost. Since the repository’s private, and I wasn’t worried about destructively rewriting history, I wondered, can I fix this using mq?

The answer was a resounding, “yes.”

First, let’s bring the entire history into mq, and save the result so that we have something to go back to in case we screw up:

~/code/bqb$ hg qimport -r 0:tip
~/code/bqb$ hg qci -m "Before address change"

Next, because we’re about to rewrite the patches themselves, we’ll pop off all of the patches:

~/code/bqb$ hg qpop -a

at which point we can safely go and make our changes with some simple sed magic.

~/code/bqb$ cd .hg/patches
~/code/bqb/.hg/patches$ sed -i -e "s/@localhost/" *.diff
~/code/bqb/.hg/patches$ hg diff

Everything looks okay, so it’s time to reapply the patches:

~/code/bqb/.hg/patches$ cd ../..
~/code/bqb$ hg qpush -a

and convert them back into changesets.

~/code/bqb$ hg qdelete -r qbase:qtip

Did it work?

~/code/bqb$ hg log | grep '@localhost'

Yep. We’re all set.

A couple of things to keep in mind if you do this:

  1. Just to state the obvious, you’re rewriting history. You will no longer be able to interact with repositories made before the rewrite. This means you should never try the above stunt on a repository you’ve shared with others. (Well, mostly. If you only run the initial qimport on changes you’ve not yet pushed out—rather than on the entire repository, as I did—you’re fine. Just be careful.)
  2. Make very sure you’ve set Mercurial to use git-style patches, or you will unwittingly annihilate blank and binary files when you convert your changesets to patches. If you’ve not yet done so, edit your ~/.hgrc so that -g is passed by default to qimport and qrefresh.
  3. Remember that whenever working with mq, you have the potential to completely lose your history. Be careful. Use hg qci to back up known-good patch states early and often.