Working With Multiple Mercurial Queues (hg mqs)
I've recently been using mercurial for revision control. I still don't like it much as git, because it tries so hard to prevent me from modifying history (modifying local history is not a bad idea) and has so many tools that do almost the same thing.
However, the MQ extension is quite nice. Even though it requires you to
learn a new set of commands (where in git you'd just use another local
branch as a queue), it does make modifying and moving through patches
somewhat easier than git rebase -i
.
This is not a tutorial in using MQs, for that see e.g. here. Instead, I'm only looking at using multiple patch queues for which very little documentation can be found online.
Creating and Moving Between Queues
The main command for interacting with queues (as opposed to patches) is
the hg qqueue
command. Its help output gives a list of the options you
use to manage queues:
-l --list list all available queues --active print name of active queue -c --create create new queue --rename rename active queue --delete delete reference to queue --purge delete queue, and remove patch dir
Each time you use hg qq --create $QNAME
to create a new patch queue
and put some patches in it, a new directory is created in
.hg/patches-$QNAME/
. Each such directory works just like the
.hg/patches/
directory does for the default queue (called 'patches').
You move between queues using hg qq $QNAME
, but must first ensure no
patches are applied, e.g. using hg qpop --all
.
To list queues and see which is active, hg qq
without options or
arguments suffices. So in practice you don't normally need the
-l/--list
or --active
options. The rest should be self-explanatory.
Moving/Copying Patches Between Queues
Since each patch queue is treated independently and you can only apply
patches from one at a time, you may find you need to move or copy
patches between queues. There is no special command for that, but the
generic patch import command hg qimport
works quite well.
Say you have a patch called 'A' in the default 'patches' queue and you
want to copy it to the current queue. You can import it using
hg qimport .hg/patches/A
from the project's base directory. The patch
gets imported and added on top on the current patch, but not applied.
Add the -P/--push
option to apply it immediately. Using this command
you create an independent copy of a patch in the second queue so any
changes in one will not be reflected in the other.
Alternatively, you can let a single copy of a patch be part of several
queues using hg qimport -e ../patches/A
. This way both queues point to
the same patch file from their series/status
files. The path part
../patches/
is actually part of the patch name in the second queue, so
this is kind of a hack.
Of course, using the same patch file only really works if the patch
applies cleanly in both queues (e.g. if it's the first patch in both).
Remember to use hg qdelete -k/--keep
if you need to delete it from one
queue – I use an
alias
qdelete = qdelete -k
. You will also not want to use
hg qqueue --purge
in this case!
Problems or Pitfalls
Unfortunately, the patch queues' use of different directories means that each of them has a separate repo if you use versioning, and patches that are part of two queues are separately versioned. You could probably work around this somehow if you really wanted to.
Note that
guards
are defined per queue. Whichever method you use to include one patch in
two queues, you need to define the guards for each patch in each queue.
You will also have to use hg qselect
separately in each queue you work
with when you e.g. move between branches.