Mercurial Queues

  • Revision slug: Mercurial_Queues
  • Revision title: Mercurial Queues
  • Revision id: 33861
  • Created:
  • Creator: jdm
  • Is current revision? No
  • Comment 84 words removed

Revision Content

Mercurial Queues, or MQ, is a Mercurial extension that lets you keep work in progress as mutable patches, instead of as immutable changesets.

Read this first! It'll save you some lost work.

  • You can destroy work with MQ. MQ puts you in a position where you're doing fairly complicated stuff to your uncommitted work. Certain operations make it easy to lose work. Watch your step.
  • hg qrefresh is destructive. It replaces your previous version of the current patch with what's in your working directory. The previous version is lost. So:
  • Use hg qcommit -m backup to keep versions of your patches.
  • Avoid the -f option. It is sharp and can mess up your repository if used incorrectly.
  • Don't use MQ in a repository anyone might pull from. MQ creates temporary changesets in your repo. If someone pulls one of them, you'll never get rid of it.
  • Ensure you use the git diff format. Otherwise you will lose any changes to binary files.
  • Ensure you have hg 1.3 or higher.

Introduction

The output of a developer (on a good day, anyway) is patches. The MQ extension lets you treat a stack of patches as works-in-progress. You can apply them as Mercurial changesets, unapply them, edit them, and when they're done, turn them into permanent changesets and push them.

Each repository has its own queue of patches managed by MQ. They're just stored as files in a special directory, repository/.hg/patches.

To enable MQ, put this in your Mecurial.ini file (see mozilla-build in https://developer.mozilla.org/en/Windows_Build_Prerequisites)  or $HOME/.hgrc file:

[extensions]
mq =

[diff]
git = 1

Don't forget the git line. This allows changing binary files in your patches.

How to use MQ for Mozilla development

The following commands demonstrate how to create an MQ entry for a single bug fix, record the changes you make, and turn them into a diff file named "bug-123456-fix.path" that is ready to be attached to the corresponding Bugzilla bug.

$ hg qnew bug-123456-fix

... change some files ...

$ hg qrefresh

... change some more files ...

$ hg qrefresh -m "Bug 123456: A brief summary of the changes you have made."
$ hg export qtip >~/bug-123456-fix.patch

While the patch is being reviewed, you might want to work on another bug. The process is exactly the same:

$ hg qnew bug-341896-fix

... change some files ...

$ hg qrefresh -m "Bug 341896: The fix, summarized briefly."
$ hg export qtip >~/bug-341896-fix.patch

If you look at the new patch file you have exported, you'll notice that it only contains the changes for your bug-341896-fix mq entry. MQ allows you to keep your unrelated changes isolated from each other. hg qseries demonstrates this:

$ hg qseries -v
0 A bug-123456-fix
1 A bug-341896-fix

This shows all of the patches you have in your queue. Let's say that the your fix for bug 123456 is reviewed, and you need to make a couple changes. MQ makes it easy to go back and fix up earlier work:

$ hg qpop
popping bug-341896-fix
now at: bug-123456-fix

$ hg qseries -v
0 A bug-123456-fix
1 U bug-341896-fix

Using qpush and qpop, you can apply and revert your patches until the one you want to modify is current.

... make the necessary changes ...
$ hg qrefresh
$ hg bzexport qtip >~/bug-123456-fix-v2.patch

If you compare bug-123456-fix.patch and bug-123456-v2.patch, you'll see your most recent changes reflected in the second. You can now qpush your way back to bug-341896-fix if you want to keep working on it, or qnew yourself an entirely new patch to work on!

The last important step is updating your mozilla-central repository. It is very dangerous to pull remote changes while you have MQ patches applied. Instead, you should pop them all before updating, like so:

$ hg qpop -a
popping bug-341896-fix
popping bug-123456-fix
patch queue now empty
$ hg pull -u
...
$ hg qpush bug-341896-fix
applying bug-123456-fix
patching file extensions/cookie/test/test_loadflags.html
Hunk #1 FAILED at 5
1 out of 1 hunks FAILED -- saving rejects to file extensions/cookie/test/test_loadflags.html.rej
errors during apply, please fix and refresh patch

It turns out that the recent changes to mozilla-central have modified the same files as your bug-123456-fix patch. You'll need to open the files that had conflicts, fix up the bits of your patch that were in conflict (look at the .rej files that are listed), and hg qrefresh the patch to save your changes.

... fix up the conflicts ...
$ hg qrefresh
$ hg qpush
applying bug-314896-fix
now at: bug-314896-fix
$ hg qpop -a
popping bug-341896-fix
popping bug-123456-fix
patch queue now empty
$ hg qpush
applying bug-123456-fix
now at: bug-123456-fix

Your patches that conflicted should now apply cleanly until the next you you update and a conflict occurs. You can learn more about advanced MQ usage from the reference page, but you should now know enough to be able to use MQ effectively for Mozilla development work.

Bugzilla Integration

Rob Arnold has made a Mercurial extension called qimportbz that makes it much easier to transfer patches between Bugzilla and your patch queue. See his blog post for more details. (Since that post was written, the command syntax has changed to: hg qimport bz:1234567)

Ted Mielczarek has made a tool that works the other way: bzexport can take patches from your patch queue and attach them to an existing bug in Bugzilla. See his blog post for details.

 

Advanced Usage and Reference

Commands

The basic MQ commands are:

hg qnew patch-name

Make a new empty patch and give it a name. The new patch is applied when it's created. That means it's a changeset. If you do hg log -r . you'll see it. All the other hg commands, like hg annotate and hg grep, see it as a regular changeset.

Note: if you want to create a patch from a bugzilla attachment or other URL, you actually want qimport not qnew.
hg qrefresh

Update the current patch to include your latest uncommitted changes. You'll do this often.

hg qcommit -m "backup"

Save a snapshot of your .hg/patches directory as a Mercurial revision in the .hg/patches repository. Do this often, too.

This does NOT save your uncommitted work. Use qrefresh to put edits into patches and qcommit to save snapshots of those patches.

hg qpop

Unapply a patch. This removes the changeset. The patch is set aside in your .hg/patches directory. You can do other work, then re-apply your patch later.

If you have multiple patches applied, you can hg qpop -a to unapply them all.

hg qpush patch-name

Apply an unapplied patch. If the patch is out of date—that is, if you've done hg update since the last time you refreshed it—then you might get rejects! The only thing to do in that case is to apply the rejects manually and hg qrefresh.

With a patch name, this applies patches until the desired patch is on top.

hg qpush -a applies them all.

hg qdelete patchname

Throw an unapplied patch away. This removes the patch from your .hg/patches directory (and from MQ's oversight generally).

This is surprisingly different than hg qdelete -r, described below.

hg qrefresh -e

qrefresh -e lets you set the commit message the way you want it. (You can use hg qrefresh -m "message" instead, if you like.)

hg qfinish or hg qdelete -r qbase

"Finish" the bottommost applied patch. It becomes a permanent changeset, suitable for pushing, using the commit message set with qrefresh.

You can only finish patches from the bottom (i.e. you can't finish a patch that's applied over unfinished patches). hg qfinish -a (or hg qdelete -r qbase:qtip) will finish all applied patches. See also #Reordering the queue below.

hg qimport -r tip

With no mq patches applied, reimport the last committed changeset into your mq. This is useful when, e.g., you forget to set a commit message for a patch before qfinishing it.

hg qimport filename_or_url

Import a patch into your queue, e.g. from Bugzilla. It is unapplied by default and the filename_or_url is the patchname. You can directly import a Bugzilla patch by using the Bugzilla attachment URL as the argument. In that case you may also want to use -n patch_name to specify the patch name.

Just as important are the commands that show you what's going on:

hg diff
hg status
These show you only uncommitted edits—work that's neither committed nor in an MQ patch. After a qrefresh, they'll both be empty.

 

hg qdiff

Show what the topmost applied MQ patch looks like, including any uncommitted edits you've made.

Use hg qdiff -p -U 8 to produce patches for review.

hg qseries -v

List all MQ patches. Applied patches are listed as A, and unapplied patches as U.

hg qapplied

List all the MQ patches that are applied, in queue order (that is, the order they were applied).

hg log -r qbase:qtip

Same thing, but show the changesets. (qbase and qtip are tags provided by MQ. They always point to the bottommost and topmost applied patch.)

hg qunapplied

List all the MQ patches that aren't applied, in queue order (that is, the order they would be applied, if you did hg qpush -a).

hg diff -r qparent

Export all applied patches in your queue as a single patch, without disturbing your queue.

To see more advanced commands, use hg help.

To get a patch directly into your queue:

wget -O - url-to-patch | hg qimport -n name-for-patch -

or if you are lucky

hg qimport -n name-for-patch url-to-patch 

Advanced Topics

Rebasing patches

Rebasing for dummies. When you write a patch, it's based on whatever version of the repo you had when you started working. Of course, changes are constantly being pushed to the central repository, so by the time you want to push, you'll be out of date. Your changes are based on an old revision.

       $ hg glog --template '{node|short} - {author} - {desc|firstline}\n' 
TIP -> o  cd9f8db8ee0f - Devin Naquin <dnaquin@example.com> - Bug 383223
       |
       o  103f04f54b14 - L. David Baron <dbaron@example.org> - Tests for z-ordering of text-decorations.
       |
       o  e3a4c136455b - Robert O'Callahan <robert@example.org> - Support system proxy settings on OS X, fixi
       |
       o  745e0f997344 - Robert O'Callahan <robert@example.org> - Support system proxy settings on OS X, fixi
       |
       o  9d80a1461309 - Robert O'Callahan <robert@example.org> - Support system proxy settings on OS X, fixi
       |
       o  4721deb1dd19 - Diane Trout <diane@example.org>, James Bunton <jamesbunton@example.fm> - Support syst
       |
       o  3e166c19d130 - Michael Ventnor <ventnor.bugzilla@example.com.au> - text-shadow tests (bug 10713)
       |
       o  c06307605f98 - Michael Ventnor <ventnor.bugzilla@example.com.au> - Implement text-shadow rendering.
       |
YOU ---->@  d243d3af29ed - Jason Orendorff <jorendorff@example.com> - [mq] Implement trebled fromps.
       |/
       o  1df6e4240511 - Shawn Wilsher <sdwilsh@example.com> - Bug 429987
       |
       .
       .
       . (the past)

You have two choices:

  • Go ahead and finish your patch now, then hg merge with the tip; or
  • Rebase your patch before you finish and push it.

Rebasing is considered the polite thing. Merging leaves a merge changeset in the history.

It's best not to hg pull while you have patches applied. The most foolproof way to pull and update is:

$ hg qpop -a             # Unapply all patches
$ hg pull
$ hg update
$ hg qpush patchname     # Reapply patches -- watch out for rejects!

Warning: Rebasing across changesets that touch the same files as your patches can cause conflicts when you push! If this happens, hg qpush will tell you, and it will leave .rej files in your working directory. To avoid losing work, you must manually apply these rejected changes, then hg qrefresh.

Rebasing for smarties. If you're used to Mercurial and MQ and you dislike .rej files, you might want to consider MqMerge. This technique lets you rebase using your merge program, but it's a bit complex.

Reordering the queue

Sometimes the queue ends up not being in the order you want. For example, maybe you've been working on two patches, and the second one (the topmost one in your queue) is ready to be pushed before the first one is.

If you have Mercurial 1.6 or newer, the best way to reorder your queue is hg qpush --move. For example:

$ hg qpop -a                   # Unapply all patches
$ hg qpush --move patchname    # Apply only one patch, reordering as needed

With older Mercurial versions, you can do this:

$ hg qpop -a                   # Unapply all patches
$ $EDITOR .hg/patches/series   # Rearrange the lines of the series file
$ hg qpush patchname           # Reapply patches -- watch out for rejects!

Warning: Reordering patches that touch the same file can cause conflicts when you push! If this happens, hg qpush will tell you, and it will leave .rej files in your working directory. To avoid losing work, you must manually apply these rejected changes, then hg qrefresh.

Folding multiple patches into one

The hg qfold command allows you to merge a patch into another one:

$ hg qgoto my-first-patch      # go to first patch
$ hg qfold my-second-patch     # fold second patch into it

Splitting a patch, the easy case: per-file splitting

If you have a patch that modifies file1 and file2, and you want to split it into two patches each modifying only one file, do:

$ hg qgoto my-patch
$ hg qref -X path/to/first/file            # take changes out of current patch and back into `hg diff`
$ hg qnew -f patch-modifying-first-file    # and take that into a new MQ patch

Here, the qref -X command takes the changes to the first file out of the patch, so that they now show up in hg diff and therefore get picked up by the hg qnew.

Splitting a patch, the general case, including per-hunk and per-line splitting

If you need to perform finer patch splitting, for example per-hunk or even per-line, there's a great tool for that: hg qcrecord. It's provided by the Crecord extension. Follow the instructions on that page to install it. (Note that the Crecord extension does not currently appear to support Windows.)

The qcrecord command creates a new patch in your queue from the changes in your working directory (as shown by `hg diff`) - it does not edit existing mercurial queue patches directly. To split an existing mercurial queue patch you must first move the changes out from the patch and into your working directory, then delete the (now empty) patch from your queue (since qcrecord will create a new patch, not add to that old patch). Say you have a patch in your queue called 'my-patch' that you want to split it into 'my-patch' and 'my-other-patch', you would do something like this:

$ hg diff                  # Check there are no local changes in the working directory
$ hg qgoto my-patch        # Make sure my-patch is the most recently applied
$ hg qref -X .             # Move all changes out of my-patch and into the working directory
$ hg qpop -f               # Pop my-patch from the queue so that we can delete it, leaving the changes in the working directory
$ hg qdelete my-patch      # Delete my-patch (which is now empty) from the queue
$ hg qcrecord my-patch     # Select the pieces of the diff that you want in my-patch, and save
$ hg qnew my-other-patch   # Save the remaining pieces of the original patch to the queue as 'my-other-patch'

Or, with the latest version of the Crecord extension, that can be simplified to:

$ hg diff                  # Check there are no local changes in the working directory
$ hg qgoto my-patch        # Make sure my-patch is the most recently applied
$ hg qcrefresh             # Select the pieces of the diff that you want to keep in my-patch
$ hg qnew my-other-patch   # Save the remaining pieces of the original patch to the queue as 'my-other-patch'

When you invoke qcrecord, it will open a console-based dialog allowing you to select file-by-file, hunk-by-hunk, and even line-by-line, what changes you want to record into the patch that qcrecord will create. When you first launch hg qcrecord, it shows you a list of modified files:

SELECT CHUNKS: (j/k/up/dn/pgup/pgdn) move cursor; (space/A) toggle hunk/all
 (f)old/unfold; (c)ommit applied; (q)uit; (?) help | [X]=hunk applied **=folded
[X]**M hello.cpp

Pressing 'f' toggles between folding and unfold (collapsing and expanding) the diff of hello.cpp:

SELECT CHUNKS: (j/k/up/dn/pgup/pgdn) move cursor; (space/A) toggle hunk/all
 (f)old/unfold; (c)ommit applied; (q)uit; (?) help | [X]=hunk applied **=folded
[X]    diff --git a/hello.cpp b/hello.cpp
       2 hunks, 4 lines changed

   [X]     @@ -1,4 +1,5 @@
            #include <iostrea>
      [X]  +#include <cmath>
           #include <cstdlib>

           double square(double x)

   [X]     @@ -8,5 +9,6 @@

            int main()
            {
      [X]  -  std::cout << square(3.2) << std::endl;
      [X]  +  double x = 2.0;
      [X]  +  std::cout << std::sqrt(square(x)) << std::endl;
           }

This allows us to select the lines to record in the patch. When we're done, we press 'c'.

Wanted

  • Using MQ to thaw/edit/refreeze history
  • Sharing patch repos
  • guards, maybe
  • multiple queues, maybe

Revision Source

<p><strong>Mercurial Queues</strong>, or <strong>MQ</strong>, is a <a href="/en/Mercurial" title="en/Mercurial">Mercurial</a> extension that lets you keep work in progress as mutable patches, instead of as immutable changesets.</p>
<div class="warning"> <p>Read this first! It'll save you some lost work.</p> <ul> <li><strong>You can destroy work with MQ.</strong> MQ puts you in a position where you're doing fairly complicated stuff to your uncommitted work. Certain operations make it easy to lose work. Watch your step.</li> <li><strong><code>hg qrefresh</code> is destructive.</strong> It replaces your previous version of the current patch with what's in your working directory. The previous version is lost. So:</li> <li><strong>Use <code>hg qcommit -m backup</code> to keep versions of your patches.</strong></li> <li><strong>Avoid the <code>-f</code> option.</strong> It is sharp and can mess up your repository if used incorrectly.</li> <li><strong>Don't use MQ in a repository anyone might pull from.</strong> MQ creates temporary changesets in your repo. If someone pulls one of them, you'll never get rid of it.</li> <li>Ensure you use the <strong>git diff format</strong>. Otherwise you will lose any changes to binary files.</li> <li>Ensure you have hg 1.3 or higher.</li> </ul>
</div>
<h3 name="Introduction">Introduction</h3>
<p>The output of a developer (on a good day, anyway) is patches. The MQ extension lets you treat a stack of patches as works-in-progress. You can apply them as Mercurial changesets, unapply them, edit them, and when they're done, turn them into permanent changesets and push them.</p>
<p>Each repository has its own queue of patches managed by MQ. They're just stored as files in a special directory, <code>repository/.hg/patches</code>.</p>
<p>To enable MQ, put this in your Mecurial.ini file (see mozilla-build in https://developer.mozilla.org/en/Windows_Build_Prerequisites)  or <code>$HOME/.hgrc</code> file:</p>
<pre class="eval">[extensions]
mq =

[diff]
git = 1
</pre>
<p>Don't forget the <code>git</code> line. This allows changing binary files in your patches.</p>
<h3>How to use MQ for Mozilla development</h3>
<p>The following commands demonstrate how to create an MQ entry for a single bug fix, record the changes you make, and turn them into a diff file named "bug-123456-fix.path" that is ready to be <a href="/En/Developer_Guide/How_to_Submit_a_Patch" title="https://developer.mozilla.org/En/Developer_Guide/How_to_Submit_a_Patch">attached to the corresponding Bugzilla bug</a>.</p>
<pre>$ hg qnew bug-123456-fix

... change some files ...

$ hg qrefresh

... change some more files ...

$ hg qrefresh -m "Bug 123456: A brief summary of the changes you have made."
$ hg export qtip &gt;~/bug-123456-fix.patch
</pre>
<p>While the patch is being reviewed, you might want to work on another bug. The process is exactly the same:</p>
<pre>$ hg qnew bug-341896-fix

... change some files ...

$ hg qrefresh -m "Bug 341896: The fix, summarized briefly."
$ hg export qtip &gt;~/bug-341896-fix.patch
</pre>
<p>If you look at the new patch file you have exported, you'll notice that it only contains the changes for your bug-341896-fix mq entry. MQ allows you to keep your unrelated changes isolated from each other. <strong>hg qseries </strong>demonstrates this:</p>
<pre>$ hg qseries -v
0 A bug-123456-fix
1 A bug-341896-fix
</pre>
<p>This shows all of the patches you have in your queue. Let's say that the your fix for bug 123456 is reviewed, and you need to make a couple changes. MQ makes it easy to go back and fix up earlier work:</p>
<pre>$ hg qpop
popping bug-341896-fix
now at: bug-123456-fix

$ hg qseries -v
0 A bug-123456-fix
1 U bug-341896-fix
</pre>
<p>Using qpush and qpop, you can apply and revert your patches until the one you want to modify is current.</p>
<pre>... make the necessary changes ...
$ hg qrefresh
$ hg bzexport qtip &gt;~/bug-123456-fix-v2.patch
</pre>
<p>If you compare bug-123456-fix.patch and bug-123456-v2.patch, you'll see your most recent changes reflected in the second. You can now qpush your way back to bug-341896-fix if you want to keep working on it, or qnew yourself an entirely new patch to work on!</p>
<p>The last important step is updating your mozilla-central repository. It is very dangerous to pull remote changes while you have MQ patches applied. Instead, you should pop them all before updating, like so:</p>
<pre>$ hg qpop -a
popping bug-341896-fix
popping bug-123456-fix
patch queue now empty
$ hg pull -u
...
$ hg qpush bug-341896-fix
applying bug-123456-fix
patching file extensions/cookie/test/test_loadflags.html
Hunk #1 FAILED at 5
1 out of 1 hunks FAILED -- saving rejects to file extensions/cookie/test/test_loadflags.html.rej
errors during apply, please fix and refresh patch
</pre>
<p>It turns out that the recent changes to mozilla-central have modified the same files as your bug-123456-fix patch. You'll need to open the files that had conflicts, fix up the bits of your patch that were in conflict (look at the .rej files that are listed), and <code>hg qrefresh</code> the patch to save your changes.</p>
<pre>... fix up the conflicts ...
$ hg qrefresh
$ hg qpush
applying bug-314896-fix
now at: bug-314896-fix
$ hg qpop -a
popping bug-341896-fix
popping bug-123456-fix
patch queue now empty
$ hg qpush
applying bug-123456-fix
now at: bug-123456-fix
</pre>
<p>Your patches that conflicted should now apply cleanly until the next you you update and a conflict occurs. You can learn more about advanced MQ usage from the reference page, but you should now know enough to be able to use MQ effectively for Mozilla development work.</p>
<h3 name="Introduction">Bugzilla Integration</h3>
<p>Rob Arnold has made a Mercurial extension called <code>qimportbz</code> that makes it much easier to transfer patches between Bugzilla and your patch queue. See his <a class="external" href="http://robarnold.org/hg-qimport-my-bugzilla-patch-redux/" title="http://robarnold.org/hg-qimport-my-bugzilla-patch-redux/">blog post</a> for more details. (Since that post was written, the command syntax has changed to: <code>hg qimport bz:1234567</code>)<code> </code></p>
<p>Ted Mielczarek has made a tool that works the other way: <code>bzexport</code> can take patches from your patch queue and attach them to an existing bug in Bugzilla. See his <a class="external" href="http://blog.mozilla.com/ted/2010/09/07/bzexport-a-mercurial-extension/">blog post</a> for details.</p>
<p> </p>
<h2>Advanced Usage and Reference</h2>
<h3 name="Commands">Commands</h3>
<p>The basic MQ commands are:</p>
<dl> <dt><code>hg qnew <var>patch-name</var></code></dt> <dd> <p>Make a new empty patch and give it a name. The new patch is <em>applied</em> when it's created. That means it's a changeset. If you do <code>hg log -r .</code> you'll see it. All the other <code>hg</code> commands, like <code>hg annotate</code> and <code>hg grep</code>, see it as a regular changeset.</p> Note: if you want to create a patch from a bugzilla attachment or other URL, you actually want qimport not qnew.</dd> <dt><code>hg qrefresh</code></dt> <dd> <p>Update the current patch to include your latest uncommitted changes. You'll do this often.</p> </dd> <dt><code>hg qcommit -m "backup"</code></dt> <dd> <p>Save a snapshot of your <code>.hg/patches</code> directory as a Mercurial revision in the <code>.hg/patches</code> repository. Do this often, too.</p> <p>This does <em>NOT</em> save your uncommitted work. Use <code>qrefresh</code> to put edits into patches and <code>qcommit</code> to save snapshots of those patches.</p> </dd> <dt><code>hg qpop</code></dt> <dd> <p><em>Unapply</em> a patch. This removes the changeset. The patch is set aside in your <code>.hg/patches</code> directory. You can do other work, then re-apply your patch later.</p> <p>If you have multiple patches applied, you can <code>hg qpop -a</code> to unapply them all.</p> </dd> <dt><code>hg qpush <var>patch-name</var></code></dt> <dd> <p>Apply an unapplied patch. If the patch is out of date—that is, if you've done <code>hg update</code> since the last time you refreshed it—then you might get rejects! The only thing to do in that case is to apply the rejects manually and <code>hg qrefresh</code>.</p> <p>With a patch name, this applies patches until the desired patch is on top.</p> <p><code>hg qpush -a</code> applies them all.</p> </dd> <dt><code>hg qdelete <var>patchname</var></code></dt> <dd> <p>Throw an unapplied patch away. This removes the patch from your <code>.hg/patches</code> directory (and from MQ's oversight generally).</p> <p>This is surprisingly different than <code>hg qdelete -r</code>, described below.</p> </dd> <dt><code>hg qrefresh -e</code></dt> <dd> <p><code>qrefresh -e</code> lets you set the commit message the way you want it. (You can use <code>hg qrefresh -m "message"</code> instead, if you like.)</p> </dd> <dt><code>hg qfinish</code> or <code>hg qdelete -r qbase</code></dt> <dd> <p>"Finish" the bottommost applied patch. It becomes a permanent changeset, suitable for pushing, using the commit message set with <code>qrefresh</code>.</p> <p>You can only finish patches from the bottom (i.e. you can't finish a patch that's applied over unfinished patches). <code>hg qfinish -a</code> (or <code>hg qdelete -r qbase:qtip</code>) will finish all applied patches. See also <a href="#Reordering_the_queue">#Reordering the queue</a> below.</p> </dd> <dt><code>hg qimport -r tip</code></dt> <dd> <p><strong>With no mq patches applied</strong>, reimport the last committed changeset into your mq. This is useful when, e.g., you forget to set a commit message for a patch before <code>qfinish</code>ing it.</p> </dd> <dt><strong>hg qimport </strong><em><strong>filename_or_url</strong></em></dt> <dd> <p>Import a patch into your queue, e.g. from Bugzilla. It is unapplied by default and the <em>filename_or_url</em> is the <em>patchname</em>. You can directly import a Bugzilla patch by using the Bugzilla attachment URL as the argument. In that case you may also want to use <code>-n <strong>patch_name</strong></code> to specify the patch name.</p> </dd>
</dl>
<p>Just as important are the commands that show you what's going on:</p>
<dl> <dt><code>hg diff</code></dt> <dt><code>hg status</code></dt> <dd>These show you only uncommitted edits—work that's neither committed nor in an MQ patch. After a <code>qrefresh</code>, they'll both be empty. <p> </p> </dd> <dt><code>hg qdiff</code></dt> <dd> <p>Show what the topmost applied MQ patch looks like, <em>including</em> any uncommitted edits you've made.</p> <p>Use <strong><code>hg qdiff -p -U 8</code></strong> to produce patches for review.</p> </dd> <dt><code>hg qseries -v</code></dt> <dd> <p>List all MQ patches. Applied patches are listed as <code>A</code>, and unapplied patches as <code>U</code>.</p> </dd> <dt><code>hg qapplied</code></dt> <dd> <p>List all the MQ patches that are applied, in queue order (that is, the order they were applied).</p> </dd> <dt><code>hg log -r qbase:qtip</code></dt> <dd> <p>Same thing, but show the changesets. (<code>qbase</code> and <code>qtip</code> are tags provided by MQ. They always point to the bottommost and topmost applied patch.)</p> </dd> <dt><code>hg qunapplied</code></dt> <dd> <p>List all the MQ patches that aren't applied, in queue order (that is, the order they would be applied, if you did <code>hg qpush -a</code>).</p> </dd> <dt><code>hg diff -r qparent</code></dt> <dd> <p>Export all applied patches in your queue as a single patch, without disturbing your queue.</p> </dd>
</dl>
<p>To see more advanced commands, use <strong><code>hg help</code></strong>.</p>
<p>To get a patch directly into your queue:</p>
<pre class="eval">wget -O - url-to-patch | hg qimport -n name-for-patch -</pre>
<p>or if you are lucky</p>
<pre class="eval">hg qimport -n name-for-patch url-to-patch </pre>
<h3 name="Advanced_Topics">Advanced Topics</h3>
<h4 name="Rebasing_patches">Rebasing patches</h4>
<p><strong>Rebasing for dummies.</strong> When you write a patch, it's based on whatever version of the repo you had when you started working. Of course, changes are constantly being pushed to the central repository, so by the time you want to push, you'll be out of date. Your changes are <em>based on</em> an old revision.</p>
<pre class="eval">       $ <strong>hg glog --template '{node|short} - {author} - {desc|firstline}\n' </strong>
<strong>TIP -&gt;</strong> o  cd9f8db8ee0f - Devin Naquin &lt;<a class=" link-mailto" href="mailto:dnaquin@example.com" rel="freelink">dnaquin@example.com</a>&gt; - Bug 383223
       |
       o  103f04f54b14 - L. David Baron &lt;<a class=" link-mailto" href="mailto:dbaron@example.org" rel="freelink">dbaron@example.org</a>&gt; - Tests for z-ordering of text-decorations.
       |
       o  e3a4c136455b - Robert O'Callahan &lt;<a class=" link-mailto" href="mailto:robert@example.org" rel="freelink">robert@example.org</a>&gt; - Support system proxy settings on OS X, fixi
       |
       o  745e0f997344 - Robert O'Callahan &lt;<a class=" link-mailto" href="mailto:robert@example.org" rel="freelink">robert@example.org</a>&gt; - Support system proxy settings on OS X, fixi
       |
       o  9d80a1461309 - Robert O'Callahan &lt;<a class=" link-mailto" href="mailto:robert@example.org" rel="freelink">robert@example.org</a>&gt; - Support system proxy settings on OS X, fixi
       |
       o  4721deb1dd19 - Diane Trout &lt;<a class=" link-mailto" href="mailto:diane@example.org" rel="freelink">diane@example.org</a>&gt;, James Bunton &lt;<a class=" link-mailto" href="mailto:jamesbunton@example.fm" rel="freelink">jamesbunton@example.fm</a>&gt; - Support syst
       |
       o  3e166c19d130 - Michael Ventnor &lt;<a class=" link-mailto" href="mailto:ventnor.bugzilla@example.com.au" rel="freelink">ventnor.bugzilla@example.com.au</a>&gt; - text-shadow tests (bug 10713)
       |
       o  c06307605f98 - Michael Ventnor &lt;<a class=" link-mailto" href="mailto:ventnor.bugzilla@example.com.au" rel="freelink">ventnor.bugzilla@example.com.au</a>&gt; - Implement text-shadow rendering.
       |
<strong>YOU ----&gt;</strong>@  d243d3af29ed - Jason Orendorff &lt;<a class=" link-mailto" href="mailto:jorendorff@example.com" rel="freelink">jorendorff@example.com</a>&gt; - [mq] Implement trebled fromps.
       |/
       o  1df6e4240511 - Shawn Wilsher &lt;<a class=" link-mailto" href="mailto:sdwilsh@example.com" rel="freelink">sdwilsh@example.com</a>&gt; - Bug 429987
       |
       .
       .
       . (the past)
</pre>
<p>You have two choices:</p>
<ul> <li>Go ahead and finish your patch now, then <code>hg merge</code> with the tip; or</li> <li><em>Rebase</em> your patch before you finish and push it.</li>
</ul>
<p>Rebasing is considered the polite thing. Merging leaves a merge changeset in the history.</p>
<p>It's best not to <code>hg pull</code> while you have patches applied. The most foolproof way to pull and update is:</p>
<pre class="eval">$ <strong>hg qpop -a</strong>             <em># Unapply all patches</em>
$ <strong>hg pull</strong>
$ <strong>hg update</strong>
$ <strong>hg qpush <var>patchname</var></strong>     <em># Reapply patches -- watch out for rejects!</em>
</pre>
<p>Warning: Rebasing across changesets that touch the same files as your patches can cause conflicts when you push! If this happens, <code>hg qpush</code> will tell you, and it will leave <code>.rej</code> files in your working directory. To avoid losing work, you must manually apply these rejected changes, then <code>hg qrefresh</code>.</p>
<p><strong>Rebasing for smarties.</strong> If you're used to Mercurial and MQ and you dislike <code>.rej</code> files, you might want to consider <a class="external" href="http://www.selenic.com/mercurial/wiki/index.cgi/MqMerge">MqMerge</a>. This technique lets you rebase using your merge program, but it's a bit complex.</p>
<h4 name="Reordering_the_queue">Reordering the queue</h4>
<p>Sometimes the queue ends up not being in the order you want. For example, maybe you've been working on two patches, and the second one (the topmost one in your queue) is ready to be pushed before the first one is.</p>
<p>If you have Mercurial 1.6 or newer, the best way to reorder your queue is <code>hg qpush --move. For example:</code></p>
<pre>$ <strong>hg qpop -a</strong>                   <em># Unapply all patches
</em>$ <strong>hg qpush --move patchname</strong>    <em># Apply only one patch, reordering as needed</em></pre>
<p>With older Mercurial versions, you can do this:</p>
<pre class="eval">$ <strong>hg qpop -a</strong>                   <em># Unapply all patches</em>
$ <strong>$EDITOR .hg/patches/series</strong>   <em># Rearrange the lines of the series file</em>
$ <strong>hg qpush <var>patchname</var></strong>           <em># Reapply patches -- watch out for rejects!</em>
</pre>
<p>Warning: Reordering patches that touch the same file can cause conflicts when you push! If this happens, <code>hg qpush</code> will tell you, and it will leave <code>.rej</code> files in your working directory. To avoid losing work, you must manually apply these rejected changes, then <code>hg qrefresh</code>.</p>
<h4>Folding multiple patches into one</h4>
<p>The <code>hg qfold </code>command allows you to merge a patch into another one:</p>
<pre>$ <strong>hg qgoto my-first-patch</strong>      <em># go to first patch</em>
$ <strong>hg qfold my-second-patch</strong>     <em># fold second patch into it</em>
</pre>
<h4 name="Wanted">Splitting a patch, the easy case: per-file splitting</h4>
<p>If you have a patch that modifies <code>file1</code> and <code>file2</code>, and you want to split it into two patches each modifying only one file, do:</p>
<pre>$ <strong>hg qgoto my-patch</strong>
$ <strong>hg qref -X path/to/first/file</strong>            # take changes out of current patch and back into `hg diff`
$ <strong>hg qnew -f patch-modifying-first-file</strong>    # and take that into a new MQ patch
</pre>
<p>Here, the <code>qref -X</code> command takes the changes to the first file out of the patch, so that they now show up in <code>hg diff</code> and therefore get picked up by the <code>hg qnew.</code></p>
<h4>Splitting a patch, the general case, including per-hunk and per-line splitting</h4>
<p>If you need to perform finer patch splitting, for example per-hunk or even per-line, there's a great tool for that: <code>hg qcrecord.</code> It's provided by the <a class="external" href="http://mercurial.selenic.com/wiki/CrecordExtension" title="http://mercurial.selenic.com/wiki/CrecordExtension">Crecord extension</a>. Follow the instructions on that page to install it. (Note that the Crecord extension does <em>not</em> currently appear to support Windows.)</p>
<p>The qcrecord command creates a <u><strong>new</strong></u> patch in your queue from the changes in your <u><strong>working directory</strong></u> (as shown by `<code>hg diff</code>`) - it does <u><strong>not</strong></u> edit existing mercurial queue patches <strong>directly</strong>. To split an existing mercurial queue patch you must first move the changes out from the patch and into your working directory, then delete the (now empty) patch from your queue (since qcrecord will create a new patch, not add to that old patch). Say you have a patch in your queue called 'my-patch' that you want to split it into 'my-patch' and 'my-other-patch', you would do something like this:</p>
<pre>$ <strong>hg diff</strong>                  # Check there are no local changes in the working directory
$ <strong>hg qgoto my-patch</strong>        # Make sure my-patch is the most recently applied
$ <strong>hg qref -X .</strong>             # Move all changes out of my-patch and into the working directory
$ <strong>hg qpop -f</strong>               # Pop my-patch from the queue so that we can delete it, leaving the changes in the working directory
$ <strong>hg qdelete my-patch</strong>      # Delete my-patch (which is now empty) from the queue
$ <strong>hg qcrecord my-patch</strong>     # Select the pieces of the diff that you want in my-patch, and save
$ <strong>hg qnew my-other-patch</strong>   # Save the remaining pieces of the original patch to the queue as 'my-other-patch'
</pre>
<p>Or, with the latest version of the Crecord extension, that can be simplified to:</p>
<pre>$ <strong>hg diff</strong>                  # Check there are no local changes in the working directory
$ <strong>hg qgoto my-patch</strong>        # Make sure my-patch is the most recently applied
$ <strong>hg qcrefresh</strong>             # Select the pieces of the diff that you want to keep in my-patch
$ <strong>hg qnew my-other-patch</strong>   # Save the remaining pieces of the original patch to the queue as 'my-other-patch'
</pre>
<p>When you invoke qcrecord, it will open a console-based dialog allowing you to select file-by-file, hunk-by-hunk, and even line-by-line, what changes you want to record into the patch that qcrecord will create. When you first launch hg qcrecord, it shows you a list of modified files:</p>
<pre>SELECT CHUNKS: (j/k/up/dn/pgup/pgdn) move cursor; (space/A) toggle hunk/all
 (f)old/unfold; (c)ommit applied; (q)uit; (?) help | [X]=hunk applied **=folded
[X]**M hello.cpp
</pre>
<p>Pressing 'f' toggles between folding and unfold (collapsing and expanding) the diff of hello.cpp:</p>
<pre>SELECT CHUNKS: (j/k/up/dn/pgup/pgdn) move cursor; (space/A) toggle hunk/all
 (f)old/unfold; (c)ommit applied; (q)uit; (?) help | [X]=hunk applied **=folded
[X]    diff --git a/hello.cpp b/hello.cpp
       2 hunks, 4 lines changed

   [X]     @@ -1,4 +1,5 @@
            #include &lt;iostrea&gt;
      [X]  +#include &lt;cmath&gt;
           #include &lt;cstdlib&gt;

           double square(double x)

   [X]     @@ -8,5 +9,6 @@

            int main()
            {
      [X]  -  std::cout &lt;&lt; square(3.2) &lt;&lt; std::endl;
      [X]  +  double x = 2.0;
      [X]  +  std::cout &lt;&lt; std::sqrt(square(x)) &lt;&lt; std::endl;
           }
</pre>
<p>This allows us to select the lines to record in the patch. When we're done, we press 'c'.</p>
<h4>Wanted</h4>
<ul> <li>Using MQ to thaw/edit/refreeze history</li> <li>Sharing patch repos</li> <li>guards, maybe</li> <li>multiple queues, maybe</li>
</ul>
Revert to this revision