Mercurial_ The Definitive Guide - Bryan O'Sullivan [97]
It is also possible to turn an existing changeset into a patch, by passing the -r option to hg qimport.
$ hg qimport -r tip
$ hg qapplied
0.diff
Note that it only makes sense to convert a changeset into a patch if you have not propagated that changeset into any other repositories. The imported changeset’s ID will change every time you refresh the patch, which will make Mercurial treat it as unrelated to the original changeset if you have pushed it somewhere else.
Getting the Best Performance Out of MQ
MQ is very efficient at handling a large number of patches. I ran some performance experiments in mid-2006 for a talk that I gave at the 2006 EuroPython conference (on modern hardware, you should expect better performance than you’ll see below). I used as my data set the Linux 2.6.17-mm1 patch series, which consists of 1,738 patches. I applied these on top of a Linux kernel repository containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux 2.6.17.
On my old, slow laptop, I was able to hg qpush hg -a all 1,738 patches in 3.5 minutes, and hg qpop hg -a them all in 30 seconds. (On a newer laptop, the time to push all patches dropped to two minutes.) I could qrefresh one of the biggest patches (which made 22,779 lines of changes to 287 files) in 6.6 seconds.
Clearly, MQ is well suited to working in large trees, but there are a few tricks you can use to get the best performance out of it.
First of all, try to “batch” operations together. Every time you run qpush or qpop, these commands scan the working directory once to make sure you haven’t made some changes and then forgotten to run qrefresh. On a small tree, the time that this scan takes is unnoticeable. However, on a medium-sized tree (containing tens of thousands of files), it can take a second or more.
The qpush and qpop commands allow you to push and pop multiple patches at a time. You can identify the “destination patch” that you want to end up at. When you qpush with a destination specified, it will push patches until that patch is at the top of the applied stack. When you qpop to a destination, MQ will pop patches until the destination patch is at the top.
You can identify a destination patch using either the name of the patch, or by number. If you use numeric addressing, patches are counted from zero; this means that the first patch is zero, the second is one, and so on.
Updating Your Patches When the Underlying Code Changes
It’s common to have a stack of patches on top of an underlying repository that you don’t modify directly. If you’re working on changes to third-party code, or on a feature that is taking longer to develop than the rate of change of the code beneath, you will often need to sync up with the underlying code, and fix up any hunks in your patches that no longer apply. This is called rebasing your patch series.
The simplest way to do this is to hg qpop hg -a your patches, then hg pull changes into the underlying repository, and finally hg qpush hg -a your patches again. MQ will stop pushing any time it runs across a patch that fails to apply during conflicts, allowing you to fix your conflicts, qrefresh the affected patch, and continue pushing until you have fixed your entire stack.
This approach is easy to use and works well if you don’t expect changes to the underlying code to affect how well your patches apply. If your patch stack touches code that is modified frequently or invasively in the underlying repository, however, fixing up rejected hunks by hand quickly becomes tiresome.
It’s possible to partially automate the rebasing process. If your patches apply cleanly against some revision of the underlying repo, MQ can use this information to help you to resolve conflicts between your patches and a different revision.
The process is a little involved:
To begin, hg qpush -a all of your patches on top of the revision where you know that they apply cleanly.
Save a backup copy of your patch directory using hg qsave hg -e hg -c. This prints the