changeset 104:32bf9a5f22c0

Refactor MQ chapter into three. Start text on guards.
author Bryan O'Sullivan <bos@serpentine.com>
date Fri, 20 Oct 2006 16:56:20 -0700
parents 5b80c922ebdd
children ecacb6b4c9fd
files en/00book.tex en/Makefile en/examples/mq.guards en/mq-collab.tex en/mq-ref.tex en/mq.tex
diffstat 6 files changed, 589 insertions(+), 346 deletions(-) [+]
line wrap: on
line diff
--- a/en/00book.tex	Thu Oct 19 15:18:07 2006 -0700
+++ b/en/00book.tex	Fri Oct 20 16:56:20 2006 -0700
@@ -44,6 +44,8 @@
 \include{hook}
 \include{template}
 \include{mq}
+\include{mq-collab}
+\include{mq-ref}
 
 \appendix
 \include{srcinstall}
--- a/en/Makefile	Thu Oct 19 15:18:07 2006 -0700
+++ b/en/Makefile	Fri Oct 20 16:56:20 2006 -0700
@@ -12,6 +12,8 @@
 	hook.tex \
 	intro.tex \
 	mq.tex \
+	mq-collab.tex \
+	mq-ref.tex \
 	preface.tex \
 	srcinstall.tex \
 	template.tex \
@@ -34,6 +36,7 @@
 	hook.msglen \
 	hook.simple \
 	hook.ws \
+	mq.guards \
 	mq.qinit-help \
 	mq.dodiff \
 	mq.id \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/examples/mq.guards	Fri Oct 20 16:56:20 2006 -0700
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+echo '[extensions]' >> $HGRC
+echo 'hgext.mq =' >> $HGRC
+
+hg init a
+cd a
+
+#$ name: init
+
+hg qinit
+hg qnew hello.patch
+echo hello > hello
+hg add hello
+hg qrefresh
+hg qnew goodbye.patch
+echo goodbye > goodbye
+hg add goodbye
+hg qrefresh
+
+#$ name: qguard
+
+hg qguard
+
+#$ name: qguard.pos
+
+hg qguard +foo
+hg qguard
+
+#$ name: qguard.neg
+
+hg qguard hello.patch -quux
+hg qguard hello.patch
+
+#$ name: series
+
+cat .hg/patches/series
+
+#$ name: qselect.foo
+
+hg qpop -a
+hg qselect
+hg qselect foo
+hg qselect
+
+#$ name: qselect.cat
+
+cat .hg/patches/guards
+
+#$ name: qselect.qpush
+hg qpush -a
+
+#$ name: qselect.error
+
+hg qselect +foo
+
+#$ name: qselect.quux
+
+hg qselect quux
+hg qpop -a
+hg qpush -a
+
+#$ name: qselect.foobar
+
+hg qselect foo bar
+hg qpop -a
+hg qpush -a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/mq-collab.tex	Fri Oct 20 16:56:20 2006 -0700
@@ -0,0 +1,164 @@
+\chapter{Advanced uses of Mercurial Queues}
+
+While it's easy to pick up straightforward uses of Mercurial Queues,
+use of a little discipline and some of MQ's less frequently used
+capabilities makes it possible to work in complicated development
+environments.
+
+In this chapter, I will discuss a technique I have developed to manage
+the development of an Infiniband device driver for the Linux kernel.
+The driver in question is large (at least as drivers go), with 25,000
+lines of code spread across 35 source files.  It is maintained by a
+small team of developers.
+
+While much of the material in this chapter is specific to Linux, the
+same principles apply to any code base for which you're not the
+primary owner, and upon which you need to do a lot of development.
+
+\section{The problem of many targets}
+
+The Linux kernel changes rapidly, and has never been internally
+stable; developers frequently make drastic changes between releases.
+This means that a version of the driver that works well with a
+particular released version of the kernel will not even \emph{compile}
+correctly against, typically, any other version.
+
+To maintain a driver, we have to keep a number of distinct versions of
+Linux in mind.
+\begin{itemize}
+\item One target is the main Linux kernel development tree.
+  Maintenance of the code is in this case partly shared by other
+  developers in the kernel community, who make ``drive-by''
+  modifications to the driver as they develop and refine kernel
+  subsystems.
+\item We also maintain a number of ``backports'' to older versions of
+  the Linux kernel, to support the needs of customers who are running
+  older Linux distributions that do not incorporate our drivers.
+\item Finally, we make software releases on a schedule that is
+  necessarily not aligned with those used by Linux distributors and
+  kernel developers, so that we can deliver new features to customers
+  without forcing them to upgrade their entire kernels or
+  distributions.
+\end{itemize}
+
+\subsection{Tempting approaches that don't work well}
+
+There are two ``standard'' ways to maintain a piece of software that
+has to target many different environments.
+
+The first is to maintain a number of branches, each intended for a
+single target.  The trouble with this approach is that you must
+maintain iron discipline in the flow of changes between repositories.
+A new feature or bug fix must start life in a ``pristine'' repository,
+then percolate out to every backport repository.  Backport changes are
+more limited in the branches they should propagate to; a backport
+change that is applied to a branch where it doesn't belong will
+probably stop the driver from compiling.
+
+The second is to maintain a single source tree filled with conditional
+statements that turn chunks of code on or off depending on the
+intended target.  Because these ``ifdefs'' are not allowed in the
+Linux kernel tree, a manual or automatic process must be followed to
+strip them out and yield a clean tree.  A code base maintained in this
+fashion rapidly becomes a rat's nest of conditional blocks that are
+difficult to understand and maintain.
+
+Neither of these approaches is well suited to a situation where you
+don't ``own'' the canonical copy of a source tree.  In the case of a
+Linux driver that is distributed with the standard kernel, Linus's
+tree contains the copy of the code that will be treated by the world
+as canonical.  The upstream version of ``my'' driver can be modified
+by people I don't know, without me even finding out about it until
+after the changes show up in Linus's tree.  
+
+These approaches have the added weakness of making it difficult to
+generate well-formed patches to submit upstream.
+
+In principle, Mercurial Queues seems like a good candidate to manage a
+development scenario such as the above.  While this is indeed the
+case, MQ contains a few added features that make the job more
+pleasant.
+
+\section{Conditionally applying patches with guards}
+
+Perhaps the best way to maintain sanity with so many targets is to be
+able to choose specific patches to apply for a given situation.  MQ
+provides a feature called ``guards'' (which originates with quilt's
+\texttt{guards} command) that does just this.  To start off, let's
+create a simple repository for experimenting in.
+\interaction{mq.guards.init}
+This gives us a tiny repository that contains two patches that don't
+have any dependencies on each other, because they touch different files.
+
+The idea behind conditional application is that you can ``tag'' a
+patch with a \emph{guard}, which is simply a text string of your
+choosing, then tell MQ to select specific guards to use when applying
+patches.  MQ will then either apply, or skip over, a guarded patch,
+depending on the guards that you have selected.
+
+A patch can have an arbitrary number of guards;
+each one is \emph{positive} (``apply this patch if this guard is
+selected'') or \emph{negative} (``skip this patch if this guard is
+selected'').  A patch with no guards is always applied.
+
+\section{Controlling the guards on a patch}
+
+The \hgcmd{qguard} command lets you determine which guards should
+apply to a patch, or display the guards that are already in effect.
+Without any arguments, it displays the guards on the current topmost
+patch.
+\interaction{mq.guards.qguard}
+To set a positive guard on a patch, prefix the name of the guard with
+a ``\texttt{+}''.
+\interaction{mq.guards.qguard.pos}
+To set a negative guard on a patch, prefix the name of the guard with
+a ``\texttt{-}''.
+\interaction{mq.guards.qguard.neg}
+
+\begin{note}
+  The \hgcmd{qguard} command \emph{sets} the guards on a patch; it
+  doesn't \emph{modify} them.  What this means is that if you run
+  \hgcmdargs{qguard}{+a +b} on a patch, then \hgcmdargs{qguard}{+c} on
+  the same patch, the \emph{only} guard that will be set on it
+  afterwards is \texttt{+c}.
+\end{note}
+
+Mercurial stores guards in the \sfilename{series} file; the form in
+which they are stored is easy both to understand and to edit by hand.
+(In other words, you don't have to use the \hgcmd{qguard} command if
+you don't want to; it's okay to simply edit the \sfilename{series}
+file.)
+\interaction{mq.guards.series}
+
+\section{Selecting the guards to use}
+
+The \hgcmd{qselect} command determines which guards are active at a
+given time.  The effect of this is to determine which patches MQ will
+apply the next time you run \hgcmd{qpush}.  It has no other effect; in
+particular, it doesn't do anything to patches that are already
+applied.
+
+With no arguments, the \hgcmd{qselect} command lists the guards
+currently in effect, one per line of output.  Each argument is treated
+as the name of a guard to apply.
+\interaction{mq.guards.qselect.foo}
+In case you're interested, the currently selected guards are stored in
+the \sfilename{guards} file.
+\interaction{mq.guards.qselect.cat}
+We can see the effect the selected guards have when we run
+\hgcmd{qpush}.
+\interaction{mq.guards.qselect.qpush}
+
+A guard cannot start with a ``\texttt{+}'' or ``\texttt{-}''
+character.
+\interaction{mq.guards.qselect.error}
+Changing the selected guards changes the patches that are applied.
+\interaction{mq.guards.qselect.quux}
+You can see here that negative guards take precedence over positive
+guards.
+\interaction{mq.guards.qselect.foobar}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/mq-ref.tex	Fri Oct 20 16:56:20 2006 -0700
@@ -0,0 +1,352 @@
+\chapter{Mercurial Queues reference}
+
+\section{MQ command reference}
+\label{sec:mq:cmdref}
+
+For an overview of the commands provided by MQ, use the command
+\hgcmdargs{help}{mq}.
+
+\subsection{\hgcmd{qapplied}---print applied patches}
+
+The \hgcmd{qapplied} command prints the current stack of applied
+patches.  Patches are printed in oldest-to-newest order, so the last
+patch in the list is the ``top'' patch.
+
+\subsection{\hgcmd{qcommit}---commit changes in the queue repository}
+
+The \hgcmd{qcommit} command commits any outstanding changes in the
+\sdirname{.hg/patches} repository.  This command only works if the
+\sdirname{.hg/patches} directory is a repository, i.e.~you created the
+directory using \hgcmdargs{qinit}{\hgopt{qinit}{-c}} or ran
+\hgcmd{init} in the directory after running \hgcmd{qinit}.
+
+This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}.
+
+\subsection{\hgcmd{qdelete}---delete a patch from the
+  \sfilename{series} file}
+
+The \hgcmd{qdelete} command removes the entry for a patch from the
+\sfilename{series} file in the \sdirname{.hg/patches} directory.  It
+does not pop the patch if the patch is already applied.  By default,
+it does not delete the patch file; use the \hgopt{qdel}{-f} option to
+do that.
+
+Options:
+\begin{itemize}
+\item[\hgopt{qdel}{-f}] Delete the patch file.
+\end{itemize}
+
+\subsection{\hgcmd{qdiff}---print a diff of the topmost applied patch}
+
+The \hgcmd{qdiff} command prints a diff of the topmost applied patch.
+It is equivalent to \hgcmdargs{diff}{-r-2:-1}.
+
+\subsection{\hgcmd{qfold}---merge (``fold'') several patches into one}
+
+The \hgcmd{qfold} command merges multiple patches into the topmost
+applied patch, so that the topmost applied patch makes the union of
+all of the changes in the patches in question.
+
+The patches to fold must not be applied; \hgcmd{qfold} will exit with
+an error if any is.  The order in which patches are folded is
+significant; \hgcmdargs{qfold}{a b} means ``apply the current topmost
+patch, followed by \texttt{a}, followed by \texttt{b}''.
+
+The comments from the folded patches are appended to the comments of
+the destination patch, with each block of comments separated by three
+asterisk (``\texttt{*}'') characters.  Use the \hgopt{qfold}{-e}
+option to edit the commit message for the combined patch/changeset
+after the folding has completed.
+
+Options:
+\begin{itemize}
+\item[\hgopt{qfold}{-e}] Edit the commit message and patch description
+  for the newly folded patch.
+\item[\hgopt{qfold}{-l}] Use the contents of the given file as the new
+  commit message and patch description for the folded patch.
+\item[\hgopt{qfold}{-m}] Use the given text as the new commit message
+  and patch description for the folded patch.
+\end{itemize}
+
+\subsection{\hgcmd{qheader}---display the header/description of a patch}
+
+The \hgcmd{qheader} command prints the header, or description, of a
+patch.  By default, it prints the header of the topmost applied patch.
+Given an argument, it prints the header of the named patch.
+
+\subsection{\hgcmd{qimport}---import a third-party patch into the queue}
+
+The \hgcmd{qimport} command adds an entry for an external patch to the
+\sfilename{series} file, and copies the patch into the
+\sdirname{.hg/patches} directory.  It adds the entry immediately after
+the topmost applied patch, but does not push the patch.
+
+If the \sdirname{.hg/patches} directory is a repository,
+\hgcmd{qimport} automatically does an \hgcmd{add} of the imported
+patch.
+
+\subsection{\hgcmd{qinit}---prepare a repository to work with MQ}
+
+The \hgcmd{qinit} command prepares a repository to work with MQ.  It
+creates a directory called \sdirname{.hg/patches}.
+
+Options:
+\begin{itemize}
+\item[\hgopt{qinit}{-c}] Create \sdirname{.hg/patches} as a repository
+  in its own right.  Also creates a \sfilename{.hgignore} file that
+  will ignore the \sfilename{status} file.
+\end{itemize}
+
+When the \sdirname{.hg/patches} directory is a repository, the
+\hgcmd{qimport} and \hgcmd{qnew} commands automatically \hgcmd{add}
+new patches.
+
+\subsection{\hgcmd{qnew}---create a new patch}
+
+The \hgcmd{qnew} command creates a new patch.  It takes one mandatory
+argument, the name to use for the patch file.  The newly created patch
+is created empty by default.  It is added to the \sfilename{series}
+file after the current topmost applied patch, and is immediately
+pushed on top of that patch.
+
+If \hgcmd{qnew} finds modified files in the working directory, it will
+refuse to create a new patch unless the \hgopt{qnew}{-f} option is
+used (see below).  This behaviour allows you to \hgcmd{qrefresh} your
+topmost applied patch before you apply a new patch on top of it.
+
+Options:
+\begin{itemize}
+\item[\hgopt{qnew}{-f}] Create a new patch if the contents of the
+  working directory are modified.  Any outstanding modifications are
+  added to the newly created patch, so after this command completes,
+  the working directory will no longer be modified.
+\item[\hgopt{qnew}{-m}] Use the given text as the commit message.
+  This text will be stored at the beginning of the patch file, before
+  the patch data.
+\end{itemize}
+
+\subsection{\hgcmd{qnext}---print the name of the next patch}
+
+The \hgcmd{qnext} command prints the name name of the next patch in
+the \sfilename{series} file after the topmost applied patch.  This
+patch will become the topmost applied patch if you run \hgcmd{qpush}.
+
+\subsection{\hgcmd{qpop}---pop patches off the stack}
+
+The \hgcmd{qpop} command removes applied patches from the top of the
+stack of applied patches.  By default, it removes only one patch.
+
+This command removes the changesets that represent the popped patches
+from the repository, and updates the working directory to undo the
+effects of the patches.
+
+This command takes an optional argument, which it uses as the name or
+index of the patch to pop to.  If given a name, it will pop patches
+until the named patch is the topmost applied patch.  If given a
+number, \hgcmd{qpop} treats the number as an index into the entries in
+the series file, counting from zero (empty lines and lines containing
+only comments do not count).  It pops patches until the patch
+identified by the given index is the topmost applied patch.
+
+The \hgcmd{qpop} command does not read or write patches or the
+\sfilename{series} file.  It is thus safe to \hgcmd{qpop} a patch that
+you have removed from the \sfilename{series} file, or a patch that you
+have renamed or deleted entirely.  In the latter two cases, use the
+name of the patch as it was when you applied it.
+
+By default, the \hgcmd{qpop} command will not pop any patches if the
+working directory has been modified.  You can override this behaviour
+using the \hgopt{qpop}{-f} option, which reverts all modifications in
+the working directory.
+
+Options:
+\begin{itemize}
+\item[\hgopt{qpop}{-a}] Pop all applied patches.  This returns the
+  repository to its state before you applied any patches.
+\item[\hgopt{qpop}{-f}] Forcibly revert any modifications to the
+  working directory when popping.
+\item[\hgopt{qpop}{-n}] Pop a patch from the named queue.
+\end{itemize}
+
+The \hgcmd{qpop} command removes one line from the end of the
+\sfilename{status} file for each patch that it pops.
+
+\subsection{\hgcmd{qprev}---print the name of the previous patch}
+
+The \hgcmd{qprev} command prints the name of the patch in the
+\sfilename{series} file that comes before the topmost applied patch.
+This will become the topmost applied patch if you run \hgcmd{qpop}.
+
+\subsection{\hgcmd{qpush}---push patches onto the stack}
+\label{sec:mq:cmd:qpush}
+
+The \hgcmd{qpush} command adds patches onto the applied stack.  By
+default, it adds only one patch.
+
+This command creates a new changeset to represent each applied patch,
+and updates the working directory to apply the effects of the patches.
+
+The default data used when creating a changeset are as follows:
+\begin{itemize}
+\item The commit date and time zone are the current date and time
+  zone.  Because these data are used to compute the identity of a
+  changeset, this means that if you \hgcmd{qpop} a patch and
+  \hgcmd{qpush} it again, the changeset that you push will have a
+  different identity than the changeset you popped.
+\item The author is the same as the default used by the \hgcmd{commit}
+  command.
+\item The commit message is any text from the patch file that comes
+  before the first diff header.  If there is no such text, a default
+  commit message is used that identifies the name of the patch.
+\end{itemize}
+If a patch contains a Mercurial patch header (XXX add link), the
+information in the patch header overrides these defaults.
+
+Options:
+\begin{itemize}
+\item[\hgopt{qpush}{-a}] Push all unapplied patches from the
+  \sfilename{series} file until there are none left to push.
+\item[\hgopt{qpush}{-l}] Add the name of the patch to the end
+  of the commit message.
+\item[\hgopt{qpush}{-m}] If a patch fails to apply cleanly, use the
+  entry for the patch in another saved queue to compute the parameters
+  for a three-way merge, and perform a three-way merge using the
+  normal Mercurial merge machinery.  Use the resolution of the merge
+  as the new patch content.
+\item[\hgopt{qpush}{-n}] Use the named queue if merging while pushing.
+\end{itemize}
+
+The \hgcmd{qpush} command reads, but does not modify, the
+\sfilename{series} file.  It appends one line to the \hgcmd{status}
+file for each patch that it pushes.
+
+\subsection{\hgcmd{qrefresh}---update the topmost applied patch}
+
+The \hgcmd{qrefresh} command updates the topmost applied patch.  It
+modifies the patch, removes the old changeset that represented the
+patch, and creates a new changeset to represent the modified patch.
+
+The \hgcmd{qrefresh} command looks for the following modifications:
+\begin{itemize}
+\item Changes to the commit message, i.e.~the text before the first
+  diff header in the patch file, are reflected in the new changeset
+  that represents the patch.
+\item Modifications to tracked files in the working directory are
+  added to the patch.
+\item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy},
+  \hgcmd{remove}, or \hgcmd{rename}.  Added files and copy and rename
+  destinations are added to the patch, while removed files and rename
+  sources are removed.
+\end{itemize}
+
+Even if \hgcmd{qrefresh} detects no changes, it still recreates the
+changeset that represents the patch.  This causes the identity of the
+changeset to differ from the previous changeset that identified the
+patch.
+
+Options:
+\begin{itemize}
+\item[\hgopt{qrefresh}{-e}] Modify the commit and patch description,
+  using the preferred text editor.
+\item[\hgopt{qrefresh}{-m}] Modify the commit message and patch
+  description, using the given text.
+\item[\hgopt{qrefresh}{-l}] Modify the commit message and patch
+  description, using text from the given file.
+\end{itemize}
+
+\subsection{\hgcmd{qrename}---rename a patch}
+
+The \hgcmd{qrename} command renames a patch, and changes the entry for
+the patch in the \sfilename{series} file.
+
+With a single argument, \hgcmd{qrename} renames the topmost applied
+patch.  With two arguments, it renames its first argument to its
+second.
+
+\subsection{\hgcmd{qrestore}---restore saved queue state}
+
+XXX No idea what this does.
+
+\subsection{\hgcmd{qsave}---save current queue state}
+
+XXX Likewise.
+
+\subsection{\hgcmd{qseries}---print the entire patch series}
+
+The \hgcmd{qseries} command prints the entire patch series from the
+\sfilename{series} file.  It prints only patch names, not empty lines
+or comments.  It prints in order from first to be applied to last.
+
+\subsection{\hgcmd{qtop}---print the name of the current patch}
+
+The \hgcmd{qtop} prints the name of the topmost currently applied
+patch.
+
+\subsection{\hgcmd{qunapplied}---print patches not yet applied}
+
+The \hgcmd{qunapplied} command prints the names of patches from the
+\sfilename{series} file that are not yet applied.  It prints them in
+order from the next patch that will be pushed to the last.
+
+\subsection{\hgcmd{qversion}}
+
+The \hgcmd{qversion} command prints the version of MQ that is in use.
+
+\subsection{\hgcmd{strip}---remove a revision and descendants}
+
+The \hgcmd{strip} command removes a revision, and all of its
+descendants, from the repository.  It undoes the effects of the
+removed revisions from the repository, and updates the working
+directory to the first parent of the removed revision.
+
+The \hgcmd{strip} command saves a backup of the removed changesets in
+a bundle, so that they can be reapplied if removed in error.
+
+Options:
+\begin{itemize}
+\item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed
+  with the stripped changesets in the backup bundle.
+\item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all
+  heads. XXX This should be renamed, and use \texttt{-f} to strip revs
+  when there are pending changes.
+\item[\hgopt{strip}{-n}] Do not save a backup bundle.
+\end{itemize}
+
+\section{MQ file reference}
+
+\subsection{The \sfilename{series} file}
+
+The \sfilename{series} file contains a list of the names of all
+patches that MQ can apply.  It is represented as a list of names, with
+one name saved per line.  Leading and trailing white space in each
+line are ignored.
+
+Lines may contain comments.  A comment begins with the ``\texttt{\#}''
+character, and extends to the end of the line.  Empty lines, and lines
+that contain only comments, are ignored.
+
+You will often need to edit the \sfilename{series} file by hand, hence
+the support for comments and empty lines noted above.  For example,
+you can comment out a patch temporarily, and \hgcmd{qpush} will skip
+over that patch when applying patches.  You can also change the order
+in which patches are applied by reordering their entries in the
+\sfilename{series} file.
+
+Placing the \sfilename{series} file under revision control is also
+supported; it is a good idea to place all of the patches that it
+refers to under revision control, as well.  If you create a patch
+directory using the \hgopt{qinit}{-c} option to \hgcmd{qinit}, this
+will be done for you automatically.
+
+\subsection{The \sfilename{status} file}
+
+The \sfilename{status} file contains the names and changeset hashes of
+all patches that MQ currently has applied.  Unlike the
+\sfilename{series} file, this file is not intended for editing.  You
+should not place this file under revision control, or modify it in any
+way.  It is used by MQ strictly for internal book-keeping.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- a/en/mq.tex	Thu Oct 19 15:18:07 2006 -0700
+++ b/en/mq.tex	Fri Oct 20 16:56:20 2006 -0700
@@ -838,6 +838,7 @@
   into the \sdirname{.hg/patches} directory at any time and run
   \hgcmd{init}.  Don't forget to add an entry for the
   \sfilename{status} file to the \sfilename{.hgignore} file, though
+
   (\hgcmdargs{qinit}{\hgopt{qinit}{-c}} does this for you
   automatically); you \emph{really} don't want to manage the
   \sfilename{status} file.
@@ -1019,352 +1020,6 @@
 \hgcmd{remove} commands.  There is no MQ equivalent of the quilt
 \texttt{edit} command.
 
-\section{MQ command reference}
-\label{sec:mq:cmdref}
-
-For an overview of the commands provided by MQ, use the command
-\hgcmdargs{help}{mq}.
-
-\subsection{\hgcmd{qapplied}---print applied patches}
-
-The \hgcmd{qapplied} command prints the current stack of applied
-patches.  Patches are printed in oldest-to-newest order, so the last
-patch in the list is the ``top'' patch.
-
-\subsection{\hgcmd{qcommit}---commit changes in the queue repository}
-
-The \hgcmd{qcommit} command commits any outstanding changes in the
-\sdirname{.hg/patches} repository.  This command only works if the
-\sdirname{.hg/patches} directory is a repository, i.e.~you created the
-directory using \hgcmdargs{qinit}{\hgopt{qinit}{-c}} or ran
-\hgcmd{init} in the directory after running \hgcmd{qinit}.
-
-This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}.
-
-\subsection{\hgcmd{qdelete}---delete a patch from the
-  \sfilename{series} file}
-
-The \hgcmd{qdelete} command removes the entry for a patch from the
-\sfilename{series} file in the \sdirname{.hg/patches} directory.  It
-does not pop the patch if the patch is already applied.  By default,
-it does not delete the patch file; use the \hgopt{qdel}{-f} option to
-do that.
-
-Options:
-\begin{itemize}
-\item[\hgopt{qdel}{-f}] Delete the patch file.
-\end{itemize}
-
-\subsection{\hgcmd{qdiff}---print a diff of the topmost applied patch}
-
-The \hgcmd{qdiff} command prints a diff of the topmost applied patch.
-It is equivalent to \hgcmdargs{diff}{-r-2:-1}.
-
-\subsection{\hgcmd{qfold}---merge (``fold'') several patches into one}
-
-The \hgcmd{qfold} command merges multiple patches into the topmost
-applied patch, so that the topmost applied patch makes the union of
-all of the changes in the patches in question.
-
-The patches to fold must not be applied; \hgcmd{qfold} will exit with
-an error if any is.  The order in which patches are folded is
-significant; \hgcmdargs{qfold}{a b} means ``apply the current topmost
-patch, followed by \texttt{a}, followed by \texttt{b}''.
-
-The comments from the folded patches are appended to the comments of
-the destination patch, with each block of comments separated by three
-asterisk (``\texttt{*}'') characters.  Use the \hgopt{qfold}{-e}
-option to edit the commit message for the combined patch/changeset
-after the folding has completed.
-
-Options:
-\begin{itemize}
-\item[\hgopt{qfold}{-e}] Edit the commit message and patch description
-  for the newly folded patch.
-\item[\hgopt{qfold}{-l}] Use the contents of the given file as the new
-  commit message and patch description for the folded patch.
-\item[\hgopt{qfold}{-m}] Use the given text as the new commit message
-  and patch description for the folded patch.
-\end{itemize}
-
-\subsection{\hgcmd{qheader}---display the header/description of a patch}
-
-The \hgcmd{qheader} command prints the header, or description, of a
-patch.  By default, it prints the header of the topmost applied patch.
-Given an argument, it prints the header of the named patch.
-
-\subsection{\hgcmd{qimport}---import a third-party patch into the queue}
-
-The \hgcmd{qimport} command adds an entry for an external patch to the
-\sfilename{series} file, and copies the patch into the
-\sdirname{.hg/patches} directory.  It adds the entry immediately after
-the topmost applied patch, but does not push the patch.
-
-If the \sdirname{.hg/patches} directory is a repository,
-\hgcmd{qimport} automatically does an \hgcmd{add} of the imported
-patch.
-
-\subsection{\hgcmd{qinit}---prepare a repository to work with MQ}
-
-The \hgcmd{qinit} command prepares a repository to work with MQ.  It
-creates a directory called \sdirname{.hg/patches}.
-
-Options:
-\begin{itemize}
-\item[\hgopt{qinit}{-c}] Create \sdirname{.hg/patches} as a repository
-  in its own right.  Also creates a \sfilename{.hgignore} file that
-  will ignore the \sfilename{status} file.
-\end{itemize}
-
-When the \sdirname{.hg/patches} directory is a repository, the
-\hgcmd{qimport} and \hgcmd{qnew} commands automatically \hgcmd{add}
-new patches.
-
-\subsection{\hgcmd{qnew}---create a new patch}
-
-The \hgcmd{qnew} command creates a new patch.  It takes one mandatory
-argument, the name to use for the patch file.  The newly created patch
-is created empty by default.  It is added to the \sfilename{series}
-file after the current topmost applied patch, and is immediately
-pushed on top of that patch.
-
-If \hgcmd{qnew} finds modified files in the working directory, it will
-refuse to create a new patch unless the \hgopt{qnew}{-f} option is
-used (see below).  This behaviour allows you to \hgcmd{qrefresh} your
-topmost applied patch before you apply a new patch on top of it.
-
-Options:
-\begin{itemize}
-\item[\hgopt{qnew}{-f}] Create a new patch if the contents of the
-  working directory are modified.  Any outstanding modifications are
-  added to the newly created patch, so after this command completes,
-  the working directory will no longer be modified.
-\item[\hgopt{qnew}{-m}] Use the given text as the commit message.
-  This text will be stored at the beginning of the patch file, before
-  the patch data.
-\end{itemize}
-
-\subsection{\hgcmd{qnext}---print the name of the next patch}
-
-The \hgcmd{qnext} command prints the name name of the next patch in
-the \sfilename{series} file after the topmost applied patch.  This
-patch will become the topmost applied patch if you run \hgcmd{qpush}.
-
-\subsection{\hgcmd{qpop}---pop patches off the stack}
-
-The \hgcmd{qpop} command removes applied patches from the top of the
-stack of applied patches.  By default, it removes only one patch.
-
-This command removes the changesets that represent the popped patches
-from the repository, and updates the working directory to undo the
-effects of the patches.
-
-This command takes an optional argument, which it uses as the name or
-index of the patch to pop to.  If given a name, it will pop patches
-until the named patch is the topmost applied patch.  If given a
-number, \hgcmd{qpop} treats the number as an index into the entries in
-the series file, counting from zero (empty lines and lines containing
-only comments do not count).  It pops patches until the patch
-identified by the given index is the topmost applied patch.
-
-The \hgcmd{qpop} command does not read or write patches or the
-\sfilename{series} file.  It is thus safe to \hgcmd{qpop} a patch that
-you have removed from the \sfilename{series} file, or a patch that you
-have renamed or deleted entirely.  In the latter two cases, use the
-name of the patch as it was when you applied it.
-
-By default, the \hgcmd{qpop} command will not pop any patches if the
-working directory has been modified.  You can override this behaviour
-using the \hgopt{qpop}{-f} option, which reverts all modifications in
-the working directory.
-
-Options:
-\begin{itemize}
-\item[\hgopt{qpop}{-a}] Pop all applied patches.  This returns the
-  repository to its state before you applied any patches.
-\item[\hgopt{qpop}{-f}] Forcibly revert any modifications to the
-  working directory when popping.
-\item[\hgopt{qpop}{-n}] Pop a patch from the named queue.
-\end{itemize}
-
-The \hgcmd{qpop} command removes one line from the end of the
-\sfilename{status} file for each patch that it pops.
-
-\subsection{\hgcmd{qprev}---print the name of the previous patch}
-
-The \hgcmd{qprev} command prints the name of the patch in the
-\sfilename{series} file that comes before the topmost applied patch.
-This will become the topmost applied patch if you run \hgcmd{qpop}.
-
-\subsection{\hgcmd{qpush}---push patches onto the stack}
-\label{sec:mq:cmd:qpush}
-
-The \hgcmd{qpush} command adds patches onto the applied stack.  By
-default, it adds only one patch.
-
-This command creates a new changeset to represent each applied patch,
-and updates the working directory to apply the effects of the patches.
-
-The default data used when creating a changeset are as follows:
-\begin{itemize}
-\item The commit date and time zone are the current date and time
-  zone.  Because these data are used to compute the identity of a
-  changeset, this means that if you \hgcmd{qpop} a patch and
-  \hgcmd{qpush} it again, the changeset that you push will have a
-  different identity than the changeset you popped.
-\item The author is the same as the default used by the \hgcmd{commit}
-  command.
-\item The commit message is any text from the patch file that comes
-  before the first diff header.  If there is no such text, a default
-  commit message is used that identifies the name of the patch.
-\end{itemize}
-If a patch contains a Mercurial patch header (XXX add link), the
-information in the patch header overrides these defaults.
-
-Options:
-\begin{itemize}
-\item[\hgopt{qpush}{-a}] Push all unapplied patches from the
-  \sfilename{series} file until there are none left to push.
-\item[\hgopt{qpush}{-l}] Add the name of the patch to the end
-  of the commit message.
-\item[\hgopt{qpush}{-m}] If a patch fails to apply cleanly, use the
-  entry for the patch in another saved queue to compute the parameters
-  for a three-way merge, and perform a three-way merge using the
-  normal Mercurial merge machinery.  Use the resolution of the merge
-  as the new patch content.
-\item[\hgopt{qpush}{-n}] Use the named queue if merging while pushing.
-\end{itemize}
-
-The \hgcmd{qpush} command reads, but does not modify, the
-\sfilename{series} file.  It appends one line to the \hgcmd{status}
-file for each patch that it pushes.
-
-\subsection{\hgcmd{qrefresh}---update the topmost applied patch}
-
-The \hgcmd{qrefresh} command updates the topmost applied patch.  It
-modifies the patch, removes the old changeset that represented the
-patch, and creates a new changeset to represent the modified patch.
-
-The \hgcmd{qrefresh} command looks for the following modifications:
-\begin{itemize}
-\item Changes to the commit message, i.e.~the text before the first
-  diff header in the patch file, are reflected in the new changeset
-  that represents the patch.
-\item Modifications to tracked files in the working directory are
-  added to the patch.
-\item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy},
-  \hgcmd{remove}, or \hgcmd{rename}.  Added files and copy and rename
-  destinations are added to the patch, while removed files and rename
-  sources are removed.
-\end{itemize}
-
-Even if \hgcmd{qrefresh} detects no changes, it still recreates the
-changeset that represents the patch.  This causes the identity of the
-changeset to differ from the previous changeset that identified the
-patch.
-
-Options:
-\begin{itemize}
-\item[\hgopt{qrefresh}{-e}] Modify the commit and patch description,
-  using the preferred text editor.
-\item[\hgopt{qrefresh}{-m}] Modify the commit message and patch
-  description, using the given text.
-\item[\hgopt{qrefresh}{-l}] Modify the commit message and patch
-  description, using text from the given file.
-\end{itemize}
-
-\subsection{\hgcmd{qrename}---rename a patch}
-
-The \hgcmd{qrename} command renames a patch, and changes the entry for
-the patch in the \sfilename{series} file.
-
-With a single argument, \hgcmd{qrename} renames the topmost applied
-patch.  With two arguments, it renames its first argument to its
-second.
-
-\subsection{\hgcmd{qrestore}---restore saved queue state}
-
-XXX No idea what this does.
-
-\subsection{\hgcmd{qsave}---save current queue state}
-
-XXX Likewise.
-
-\subsection{\hgcmd{qseries}---print the entire patch series}
-
-The \hgcmd{qseries} command prints the entire patch series from the
-\sfilename{series} file.  It prints only patch names, not empty lines
-or comments.  It prints in order from first to be applied to last.
-
-\subsection{\hgcmd{qtop}---print the name of the current patch}
-
-The \hgcmd{qtop} prints the name of the topmost currently applied
-patch.
-
-\subsection{\hgcmd{qunapplied}---print patches not yet applied}
-
-The \hgcmd{qunapplied} command prints the names of patches from the
-\sfilename{series} file that are not yet applied.  It prints them in
-order from the next patch that will be pushed to the last.
-
-\subsection{\hgcmd{qversion}}
-
-The \hgcmd{qversion} command prints the version of MQ that is in use.
-
-\subsection{\hgcmd{strip}---remove a revision and descendants}
-
-The \hgcmd{strip} command removes a revision, and all of its
-descendants, from the repository.  It undoes the effects of the
-removed revisions from the repository, and updates the working
-directory to the first parent of the removed revision.
-
-The \hgcmd{strip} command saves a backup of the removed changesets in
-a bundle, so that they can be reapplied if removed in error.
-
-Options:
-\begin{itemize}
-\item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed
-  with the stripped changesets in the backup bundle.
-\item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all
-  heads. XXX This should be renamed, and use \texttt{-f} to strip revs
-  when there are pending changes.
-\item[\hgopt{strip}{-n}] Do not save a backup bundle.
-\end{itemize}
-
-\section{MQ file reference}
-
-\subsection{The \sfilename{series} file}
-
-The \sfilename{series} file contains a list of the names of all
-patches that MQ can apply.  It is represented as a list of names, with
-one name saved per line.  Leading and trailing white space in each
-line are ignored.
-
-Lines may contain comments.  A comment begins with the ``\texttt{\#}''
-character, and extends to the end of the line.  Empty lines, and lines
-that contain only comments, are ignored.
-
-You will often need to edit the \sfilename{series} file by hand, hence
-the support for comments and empty lines noted above.  For example,
-you can comment out a patch temporarily, and \hgcmd{qpush} will skip
-over that patch when applying patches.  You can also change the order
-in which patches are applied by reordering their entries in the
-\sfilename{series} file.
-
-Placing the \sfilename{series} file under revision control is also
-supported; it is a good idea to place all of the patches that it
-refers to under revision control, as well.  If you create a patch
-directory using the \hgopt{qinit}{-c} option to \hgcmd{qinit}, this
-will be done for you automatically.
-
-\subsection{The \sfilename{status} file}
-
-The \sfilename{status} file contains the names and changeset hashes of
-all patches that MQ currently has applied.  Unlike the
-\sfilename{series} file, this file is not intended for editing.  You
-should not place this file under revision control, or modify it in any
-way.  It is used by MQ strictly for internal book-keeping.
-
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "00book"