mozilla

Revision 33801 of Mercurial Queues

  • Revision slug: Mercurial_Queues
  • Revision title: Mercurial Queues
  • Revision id: 33801
  • Created:
  • Creator: Jorend
  • Is current revision? No
  • Comment /* Introduction */ qpush can have rejects!

Revision Content

Mercurial Queues, or MQ, is a Mercurial extension that lets you treat patches as a sort of slushy area in between the permanently frozen, immutable changesets produced by hg commit and the uncommitted changes in your working directory.

Warnings

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

  • 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, except for hg qnew -f. Normally -f is dangerous because it's sharp. Here it's more like, -f makes assumptions, and if the assumptions are wrong you get implementation-defined, undocumented behavior.
  • 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.

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.

To enable MQ, put this in your $HOME/.hgrc file:

[extensions]
hgext.mq =

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

The basic MQ commands are:

hg qinit -c
Create the patches directory and make a separate hg repository in there for tracking your patches. Don't skip this step. The separate hg repo is kinda weird, but the good news is, you never really have to think about it or look at it... until it saves your life.
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.
Most people use hg qnew -f patch-name. The -f flag here means "take all these uncommitted changes in my working copy and make a new patch out of them".
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.
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 {{mediawiki.external('<var>patch-name</var>')}}
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 qrefresh -e
hg qdelete -r qbase
"Finish" the bottommost applied patch. It becomes a permanent changeset, suitable for pushing.
The qrefresh -e lets you set the commit message the way you want it. (You can use hg qrefresh -m "message" instead, if you like.)
The qdelete command removes the patch from your .hg/patches directory (and from MQ's oversight generally).

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

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.
hg unapplied
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 qseries
List them all.

Revision Source

<p><b>Mercurial Queues</b>, or <b>MQ</b>, is a <a href="en/Mercurial">Mercurial</a> extension that lets you treat patches as a sort of slushy area in between the permanently frozen, immutable changesets produced by <code>hg commit</code> and the uncommitted changes in your working directory.
</p>
<h3 name="Warnings"> Warnings </h3>
<p>Read this first!  It'll save you some lost work.
</p>
<ul><li> <b>MQ puts you in a position where you're doing fairly complicated stuff to your uncommitted work.</b>  Certain operations make it easy to lose work.  Watch your step.
</li></ul>
<ul><li> <b><code>hg qrefresh</code> is destructive.</b>  It replaces your previous version of the current patch with what's in your working directory.  The previous version is lost.  So:
</li></ul>
<ul><li> <b>Use <code>hg qcommit -m backup</code> to keep versions of your patches.</b>
</li></ul>
<ul><li> <b>Avoid the <code>-f</code> option, except for <code>hg qnew -f</code>.</b>  Normally <code>-f</code> is dangerous because it's sharp.  Here it's more like, <code>-f</code> makes assumptions, and if the assumptions are wrong you get implementation-defined, undocumented behavior.
</li></ul>
<ul><li> <b>Don't use MQ in a repository anyone might pull from.</b>  MQ creates temporary changesets in your repo.  If someone pulls one of them, you'll never get rid of it.
</li></ul>
<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>To enable MQ, put this in your <code>$HOME/.hgrc</code> file:
</p>
<pre class="eval">[extensions]
hgext.mq =
</pre>
<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>The basic MQ commands are:
</p>
<dl><dt><code>hg qinit -c</code>
</dt><dd>Create the patches directory and make a separate hg repository in there for tracking your patches.  Don't skip this step.  The separate hg repo is kinda weird, but the good news is, you never really have to think about it or look at it... until it saves your life.
</dd></dl>
<dl><dt><code>hg qnew <var>patch-name</var></code>
</dt><dd>Make a new empty patch and give it a name.  The new patch is <i>applied</i> 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.
</dd><dd>Most people use <code>hg qnew <b>-f</b> <var>patch-name</var></code>.  The <code>-f</code> flag here means "take all these uncommitted changes in my working copy and make a new patch out of them".
</dd></dl>
<dl><dt><code>hg qrefresh</code>
</dt><dd>Update the current patch to include your latest uncommitted changes.  You'll do this often.
</dd></dl>
<dl><dt><code>hg qcommit -m "backup"</code>
</dt><dd>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.
</dd></dl>
<dl><dt><code>hg qpop</code>
</dt><dd><i>Unapply</i> 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.
</dd><dd>If you have multiple patches applied, you can <code>hg qpop -a</code> to unapply them all.
</dd></dl>
<dl><dt><code>hg qpush {{mediawiki.external('&lt;var&gt;patch-name&lt;/var&gt;')}}</code>
</dt><dd>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>.
</dd><dd>With a patch name, this applies patches until the desired patch is on top.
</dd><dd><code>hg qpush -a</code> applies them all.
</dd></dl>
<dl><dt><code>hg qrefresh -e</code>
</dt><dt><code>hg qdelete -r qbase</code>
</dt><dd>"Finish" the bottommost<i> applied patch.  It becomes a permanent changeset, suitable for pushing.</i>
</dd><dd>The <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.)
</dd><dd>The <code>qdelete</code> command removes the patch from your <code>.hg/patches</code> directory (and from MQ's oversight generally).
</dd></dl>
<p>Just as important are the commands that show you what's going on:
</p>
<dl><dt><code>hg qapplied</code>
</dt><dd>List all the MQ patches that are applied, in queue order (that is, the order they were applied).
</dd></dl>
<dl><dt><code>hg log -r qbase:qtip</code>
</dt><dd>Same thing, but show the changesets.
</dd></dl>
<dl><dt><code>hg unapplied</code>
</dt><dd>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>).
</dd></dl>
<dl><dt><code>hg qseries</code>
</dt><dd>List them all.
</dd></dl>
Revert to this revision