hgbook

diff en/mq.tex @ 17:2668e15c76e9

MQ: write up patch rebasing.
author Bryan O'Sullivan <bos@serpentine.com>
date Tue Jul 04 15:00:18 2006 -0700 (2006-07-04)
parents 81454425eee9
children e6f4088ebe52
line diff
     1.1 --- a/en/mq.tex	Mon Jul 03 22:43:52 2006 -0700
     1.2 +++ b/en/mq.tex	Tue Jul 04 15:00:18 2006 -0700
     1.3 @@ -381,15 +381,15 @@
     1.4  
     1.5  When neither of these techniques works, \command{patch} prints a
     1.6  message saying that the hunk in question was rejected.  It saves
     1.7 -rejected hunks to a file with the same name, and an added
     1.8 -\sfilename{.rej} extension.  It also saves an unmodified copy of the
     1.9 -file with a \sfilename{.orig} extension; the copy of the file without
    1.10 -any extensions will contain any changes made by hunks that \emph{did}
    1.11 -apply cleanly.  If you have a patch that modifies \filename{foo} with
    1.12 -six hunks, and one of them fails to apply, you will have: an
    1.13 -unmodified \filename{foo.orig}, a \filename{foo.rej} containing one
    1.14 -hunk, and \filename{foo}, containing the changes made by the five
    1.15 -successful five hunks.
    1.16 +rejected hunks (also simply called ``rejects'') to a file with the
    1.17 +same name, and an added \sfilename{.rej} extension.  It also saves an
    1.18 +unmodified copy of the file with a \sfilename{.orig} extension; the
    1.19 +copy of the file without any extensions will contain any changes made
    1.20 +by hunks that \emph{did} apply cleanly.  If you have a patch that
    1.21 +modifies \filename{foo} with six hunks, and one of them fails to
    1.22 +apply, you will have: an unmodified \filename{foo.orig}, a
    1.23 +\filename{foo.rej} containing one hunk, and \filename{foo}, containing
    1.24 +the changes made by the five successful five hunks.
    1.25  
    1.26  \subsection{Beware the fuzz}
    1.27  
    1.28 @@ -420,7 +420,7 @@
    1.29  
    1.30  If your patch \emph{used to} apply cleanly, and no longer does because
    1.31  you've changed the underlying code that your patches are based on,
    1.32 -Mercurial Queues can help; see section~\ref{seq:mq:merge} for details.
    1.33 +Mercurial Queues can help; see section~\ref{sec:mq:merge} for details.
    1.34  
    1.35  Unfortunately, there aren't any great techniques for dealing with
    1.36  rejected hunks.  Most often, you'll need to view the \sfilename{.rej}
    1.37 @@ -448,10 +448,113 @@
    1.38  If you use \command{wiggle} or \command{rej}, you should be doubly
    1.39  careful to check your results when you're done.
    1.40  
    1.41 +\section{Getting the best performance out of MQ}
    1.42 +
    1.43 +MQ is very efficient at handling a large number of patches.  I ran
    1.44 +some performance experiments in mid-2006 for a talk that I gave at the
    1.45 +2006 EuroPython conference~\cite{web:europython}.  I used as my data
    1.46 +set the Linux 2.6.17-mm1 patch series, which consists of 1,738
    1.47 +patches.  I applied thes on top of a Linux kernel repository
    1.48 +containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux
    1.49 +2.6.17.
    1.50 +
    1.51 +On my old, slow laptop, I was able to
    1.52 +\hgcmdargs{qpush}{\hgopt{qpush}{-a}} all 1,738 patches in 3.5 minutes,
    1.53 +and \hgcmdargs{qpop}{\hgopt{qpop}{-a}} them all in 30 seconds.  I
    1.54 +could \hgcmd{qrefresh} one of the biggest patches (which made 22,779
    1.55 +lines of changes to 287 files) in 6.6 seconds.
    1.56 +
    1.57 +Clearly, MQ is well suited to working in large trees, but there are a
    1.58 +few tricks you can use to get the best performance of it.
    1.59 +
    1.60 +First of all, try to ``batch'' operations together.  Every time you
    1.61 +run \hgcmd{qpush} or \hgcmd{qpop}, these commands scan the working
    1.62 +directory once to make sure you haven't made some changes and then
    1.63 +forgotten to run \hgcmd{qrefresh}.  On a small tree, the time that
    1.64 +this scan takes is unnoticeable.  However, on a medium-sized tree
    1.65 +(containing tens of thousands of files), it can take a second or more.
    1.66 +
    1.67 +The \hgcmd{qpush} and \hgcmd{qpop} commands allow you to push and pop
    1.68 +multiple patches at a time.  You can identify the ``destination
    1.69 +patch'' that you want to end up at.  When you \hgcmd{qpush} with a
    1.70 +destination specified, it will push patches until that patch is at the
    1.71 +top of the applied stack.  When you \hgcmd{qpop} to a destination, MQ
    1.72 +will pop patches until the destination patch \emph{is no longer}
    1.73 +applied.
    1.74 +
    1.75 +You can identify a destination patch using either the name of the
    1.76 +patch, or by number.  If you use numeric addressing, patches are
    1.77 +counted from zero; this means that the first patch is zero, the second
    1.78 +is one, and so on.
    1.79 +
    1.80  \section{Updating your patches when the underlying code changes}
    1.81  \label{sec:mq:merge}
    1.82  
    1.83 -XXX.
    1.84 +It's common to have a stack of patches on top of an underlying
    1.85 +repository that you don't modify directly.  If you're working on
    1.86 +changes to third-party code, or on a feature that is taking longer to
    1.87 +develop than the rate of change of the code beneath, you will often
    1.88 +need to sync up with the underlying code, and fix up any hunks in your
    1.89 +patches that no longer apply.  This is called \emph{rebasing} your
    1.90 +patch series.
    1.91 +
    1.92 +The simplest way to do this is to \hgcmdargs{qpop}{\hgopt{qpop}{-a}}
    1.93 +your patches, then \hgcmd{pull} changes into the underlying
    1.94 +repository, and finally \hgcmdargs{qpush}{\hgopt{qpop}{-a}} your
    1.95 +patches again.  MQ will stop pushing any time it runs across a patch
    1.96 +that fails to apply during conflicts, allowing you to fix your
    1.97 +conflicts, \hgcmd{qrefresh} the affected patch, and continue pushing
    1.98 +until you have fixed your entire stack.
    1.99 +
   1.100 +This approach is easy to use and works well if you don't expect
   1.101 +changes to the underlying code to affect how well your patches apply.
   1.102 +If your patch stack touches code that is modified frequently or
   1.103 +invasively in the underlying repository, however, fixing up rejected
   1.104 +hunks by hand quickly becomes tiresome.
   1.105 +
   1.106 +It's possible to partially automate the rebasing process.  If your
   1.107 +patches apply cleanly against some revision of the underlying repo, MQ
   1.108 +can use this information to help you to resolve conflicts between your
   1.109 +patches and a different revision.
   1.110 +
   1.111 +The process is a little involved.
   1.112 +\begin{enumerate}
   1.113 +\item To begin, \hgcmdargs{qpush}{-a} all of your patches on top of
   1.114 +  the revision where you know that they apply cleanly.
   1.115 +\item Save a backup copy of your patch directory using
   1.116 +  \hgcmdargs{qsave}{\hgopt{qsave}{-e} \hgopt{qsave}{-c}}.  This prints
   1.117 +  the name of the directory that it has saved the patches in.  It will
   1.118 +  save the patches to a directory called
   1.119 +  \sdirname{.hg/patches.\emph{N}}, where \texttt{\emph{N}} is a small
   1.120 +  integer.  It also commits a ``save changeset'' on top of your
   1.121 +  applied patches; this is for internal book-keeping, and records the
   1.122 +  states of the \sfilename{series} and \sfilename{status} files.
   1.123 +\item Use \hgcmd{pull} to bring new changes into the underlying
   1.124 +  repository.  (Don't run \hgcmdargs{pull}{-u}; see below for why.)
   1.125 +\item Update to the new tip revision, using
   1.126 +  \hgcmdargs{update}{\hgopt{update}{-C}} to override the patches you
   1.127 +  have pushed.
   1.128 +\item Merge all patches using \hgcmdargs{qpush}{\hgopt{qpush}{-m}
   1.129 +    \hgopt{qpush}{-a}}.  The \hgopt{qpush}{-m} option to \hgcmd{qpush}
   1.130 +  tells MQ to perform a three-way merge if the patch fails to apply.
   1.131 +\end{enumerate}
   1.132 +
   1.133 +During the \hgcmdargs{qpush}{\hgopt{qpush}{-m}}, each patch in the
   1.134 +\sfilename{series} file is applied normally.  If a patch applies with
   1.135 +fuzz or rejects, MQ looks at the queue you \hgcmd{qsave}d, and
   1.136 +performs a three-way merge with the corresponding changeset.  This
   1.137 +merge uses Mercurial's normal merge machinery, so it may pop up a GUI
   1.138 +merge tool to help you to resolve problems.
   1.139 +
   1.140 +When you finish resolving the effects of a patch, MQ refreshes your
   1.141 +patch based on the result of the merge.
   1.142 +
   1.143 +At the end of this process, your repository will have one extra head
   1.144 +from the old patch queue, and a copy of the old patch queue will be in
   1.145 +\sdirname{.hg/patches.\emph{N}}. You can remove the extra head using
   1.146 +\hgcmdargs{qpop}{\hgopt{qpop}{-a} \hgopt{qpop}{-n} patches.\emph{N}}
   1.147 +or \hgcmd{strip}.  You can delete \sdirname{.hg/patches.\emph{N}} once
   1.148 +you are sure that you no longer need it as a backup.
   1.149  
   1.150  \section{Managing patches in a repository}
   1.151  
   1.152 @@ -480,20 +583,21 @@
   1.153  each other, all on top of an underlying source base that they may or
   1.154  may not control.
   1.155  
   1.156 -\subsection{MQ support for managing a patch repository}
   1.157 +\subsection{MQ support for patch repositories}
   1.158  
   1.159  MQ helps you to work with the \sdirname{.hg/patches} directory as a
   1.160  repository; when you prepare a repository for working with patches
   1.161 -using \hgcmdargs{qinit}, you can pass the \hgopt{qinit}{-c} option to
   1.162 +using \hgcmd{qinit}, you can pass the \hgopt{qinit}{-c} option to
   1.163  create the \sdirname{.hg/patches} directory as a Mercurial repository.
   1.164  
   1.165  \begin{note}
   1.166    If you forget to use the \hgopt{qinit}{-c} option, you can simply go
   1.167    into the \sdirname{.hg/patches} directory at any time and run
   1.168    \hgcmd{init}.  Don't forget to add an entry for the
   1.169 -  \filename{status} file to the \filename{.hgignore} file, though
   1.170 -  (\hgopt{qinit}{-c} does this for you automatically); you
   1.171 -  \emph{really} don't want to manage the \filename{status} file.
   1.172 +  \sfilename{status} file to the \sfilename{.hgignore} file, though
   1.173 +  (\hgcmdargs{qinit}{\hgopt{qinit}{-c}} does this for you
   1.174 +  automatically); you \emph{really} don't want to manage the
   1.175 +  \sfilename{status} file.
   1.176  \end{note}
   1.177  
   1.178  As a convenience, if MQ notices that the \dirname{.hg/patches}
   1.179 @@ -512,9 +616,10 @@
   1.180  MQ cannot automatically detect changes that you make to the patch
   1.181  directory.  If you \hgcmd{pull}, manually edit, or \hgcmd{update}
   1.182  changes to patches or the \sfilename{series} file, you will have to
   1.183 -\hgcmdargs{qpop}{-a} and then \hgcmdargs{qpush}{-a} in the underlying
   1.184 -repository to see those changes show up there.  If you forget to do
   1.185 -this, you can confuse MQ's idea of which patches are applied.
   1.186 +\hgcmdargs{qpop}{\hgopt{qpop}{-a}} and then
   1.187 +\hgcmdargs{qpush}{\hgopt{qpush}{-a}} in the underlying repository to
   1.188 +see those changes show up there.  If you forget to do this, you can
   1.189 +confuse MQ's idea of which patches are applied.
   1.190  
   1.191  \section{Commands for working with patches}
   1.192