Mercurial Queues

From Eigen
Revision as of 13:28, 4 October 2010 by Bjacob (Talk | contribs)

Jump to: navigation, search


Mercurial Queues (MQ) is an extension for Mercurial that can make you much more productive in handling patches. But it also is dangerous and can make you lose work or do wrong things with the Eigen repository if you don't use it correctly.

Only consider using MQ if you feel really comfortable already with Mercurial. This is useful for developers who need to exchange lots of patches with Bugzilla.

MQ creates a separate hg repository in your local hg repository, specifically under .hg/patches/. Think of it as a specialized hg repo to handle patches before you want to commit them to the actual hg repo.

Lots of documentation can be found on the Web, for example there.

Setting up

In your Mercurial config file, put:

[extensions]
hgext.mq =

Then create the MQ repository: enter your local hg repository, and do:

 $ hg qinit -c

Basic usage

Creating a new patch

Suppose that you have coded something (i.e. made changes in your working copy). You now want to record these changes as a patch, i.e. as a changeset in the MQ repo. Do:

 $ hg qnew -f my-wonderful-improvements

Now you can see your patch, ready to be sent for review, as this file:

 .hg/patches/my-wonderful-improvements

Notice that qnew is the only MQ command with which we will use the -f flag. With qnew, all it means is "take all my local changes into this new patch". With other MQ commands, the -f flag often means "force" which is generally dangerous.

From there, you can continue editing your working copy. The usual command:

 $ hg diff

will return the changes not yet committed as a patch.

You can use qnew -f again to create a second patch from your new changes:

 $ hg qnew -f my-additional-improvements

You now have 2 patches in your patch series or queue.

Viewing and moving around in your patch queue

Use these commands:

 $ hg qser             # list all patches in your series
 $ hg qapp             # list all applied patches
 $ hg qunapp           # list all unapplied patches
 $ hg qpop             # unapply current patch
 $ hg qpop -a          # unapply all patches
 $ hg qpop somepatch   # unapply patches until somepatch is current
 $ hg qpush            # apply first unapplied patch
 $ hg qpush -a         # apply all patches
 $ hg qpush somepatch  # apply patches until somepatch is current

Updating an existing patch

If you want to modify an existing patch, make it current (using qpop or qpush), make changes to your working copy, and do:

 $ hg qref             # refresh current patch

You can edit its commit message:

 $ hg qref -e          # use text editor to edit commit message

Importing a patch from a file

Just do:

 $ hg qimport somefile

Turning a patch into a permanent changeset

The command for this is:

 $ hg qfinish some_mq_changeset

For example, if you have exactly one patch applied and want to qfinish it, do:

 $ hg qfinish qbase

Your patch has now been removed from your queue and turned into a changeset in your real hg repository. You can now push it to the public Eigen repository.

Advanced usage

Reordering your patch queue

Say you have patch1 and patch2 in your queue, and you want to have only patch2 applied.

Problem: if you do

 $ hg qpush patch2

that will push patch1 too, because it comes first in your queue.

Solution: make sure you have Mercurial 1.6 or newer, and do:

 $ hg qpush --move patch2

Combining two patches into one

You have patch1 and patch2 (in this order), and you want to turn them into one big patch. Make patch1 be the current patch, and do:

 $ hg qfold patch2

Splitting a patch into smaller patches

You have big-patch touching files file1 and file2. You want to split it into two patches touching one file each. Do:

 $ hg qref -X file2    # take back into working copy all changes made to file2
 $ hg qnew -f patch2   # take these changes into new patch2

Undoing a bad qfinish

Make sure you have no patches applied, and do:

 $ hg qimport -r tip

Warning! This qimport command, with the -r flag, is able to import any existing changeset. It really manipulates your real hg repository: the changeset is removed from it, and moved into the patch repository. Only ever do this on a newly qfinish'ed changeset! Never ever qimport a changeset that has already been pushed to the public Eigen repository!