Using Mercurial Queues Extension
By hnhn on Feb 24, 2009
The "merge heads" problem
If you're using Mercurial revision control system for your source repository along with a couple of other developers, you're probably familiar with the following situation. You have developed your changeset and committed into your clone, being ready to push. If you're considerate, you run
hg incoming to check there are no new changesets in the parent repository, sometimes just to find out someone pushed a new changeset a minute ago. If you push without checking incoming, you're creating two heads in the parent repository, which someone has to merge (the usual changeset comment being "merge heads"). This is one situation where Mercurial patch queue is very useful.
Developing multiple changesets at once
Another situation, where Mercurial patch queues are handy is when you're working on a number of different changesets at once and you don't want to create a different repository clone for each of them (consider a repository of several gigabytes and small changesets).
Mercurial patch queue allows to manage all your work-in-progress changesets aside from your clone's
work directory. Actually, the patches are stored in
./hg/patches of your clone and can be selectively applied and unapplied.
Using the patch queue extension
Not to duplicate information available elsewhere, I suggest you to have a look at the Mercurial Queues Extension page. There's also a quick example on the MqTutorial page. You can see that it's relatively straightforward.
Following image is trying to demonstrate the flexibility of the patch queue. You can maintain patches X and Y aside from the committed revisions in your clone, typically updating your clone by:
$ hg qpop -a $ hg pull -u $ hg qpush; hg qpush
Tips & tricks
Converting the patch to a changeset
When your patch is ready to be committed as a revision, you should check and modify the revision comment by:
$ hg qref -m "revision comment"
and then you can commit the patch by:
$ hg qdel -r <patch_name>
Note that you're actually deleting the patch (which is correct), but the -r option is very important here as it makes the new revision from it (without it the patch will be deleted, but not committed!).
Working with binary files
If you commit binary files to your repository, using patch queue will fail with the default [diff] settings. You need to add the following to your
[diff] # prevent qrefresh from updating timestamps nodates=1 # force all patches to always be in git format git=1
Queue tags and useful aliases
As you may have noticed, applied patches are marked with various tags like
qparent (last revision you pulled),
qbase (first patch applied),
qtip (last patch applied). These can be used with advantage to create a couple of useful macros in the [alias] section of
[alias] # show files affected by all applied patches qpstatus = status --rev qparent # show diff for all applied patches qpdiff = diff --rev qparent # show revision history since qparent (last pulled revision) qlog = log -r qtip:qparent
Altering patch order in the queue
Sometimes you may want to modify the order in which the patches are applied. This can be done by simple qpoping all patches and modifying the
.hg/patches/series file in your clone.