hgbook
diff en/mq.tex @ 19:187702df428b
Piles of new content for MQ chapter - cookbook stuff.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Fri Jul 07 19:56:53 2006 -0700 (2006-07-07) |
parents | e6f4088ebe52 |
children | 9d5b6d303ef5 |
line diff
1.1 --- a/en/mq.tex Tue Jul 04 16:41:31 2006 -0700 1.2 +++ b/en/mq.tex Fri Jul 07 19:56:53 2006 -0700 1.3 @@ -126,6 +126,62 @@ 1.4 Because quilt does not care about revision control tools, it is still 1.5 a tremendously useful piece of software to know about for situations 1.6 where you cannot use Mercurial and MQ. 1.7 + 1.8 +\section{Understanding patches} 1.9 + 1.10 +Because MQ doesn't hide its patch-oriented nature, it is helpful to 1.11 +understand what patches are, and a little about the tools that work 1.12 +with them. 1.13 + 1.14 +The traditional Unix \command{diff} command compares two files, and 1.15 +prints a list of differences between them. The \command{patch} command 1.16 +understands these differences as \emph{modifications} to make to a 1.17 +file. Take a look at figure~\ref{ex:mq:diff} for a simple example of 1.18 +these commands in action. 1.19 + 1.20 +\begin{figure}[ht] 1.21 + \interaction{mq.diff.diff} 1.22 + \caption{Simple uses of the \command{diff} and \command{patch} commands} 1.23 + \label{ex:mq:diff} 1.24 +\end{figure} 1.25 + 1.26 +The type of file that \command{diff} generates (and \command{patch} 1.27 +takes as input) is called a ``patch'' or a ``diff''; there is no 1.28 +difference between a patch and a diff. (We'll use the term ``patch'', 1.29 +since it's more commonly used.) 1.30 + 1.31 +A patch file can start with arbitrary text; the \command{patch} 1.32 +command ignores this text, but MQ uses it as the commit message when 1.33 +creating changesets. To find the beginning of the patch content, 1.34 +\command{patch} searches for the first line that starts with the 1.35 +string ``\texttt{diff~-}''. 1.36 + 1.37 +MQ works with \emph{unified} diffs (\command{patch} can accept several 1.38 +other diff formats, but MQ doesn't). A unified diff contains two 1.39 +kinds of header. The \emph{file header} describes the file being 1.40 +modified; it contains the name of the file to modify. When 1.41 +\command{patch} sees a new file header, it looks for a file with that 1.42 +name to start modifying. 1.43 + 1.44 +After the file header comes a series of \emph{hunks}. Each hunk 1.45 +starts with a header; this identifies the range of line numbers within 1.46 +the file that the hunk should modify. Following the header, a hunk 1.47 +starts and ends with a few (usually three) lines of text from the 1.48 +unmodified file; these are called the \emph{context} for the hunk. If 1.49 +there's only a small amount of context between successive hunks, 1.50 +\command{diff} doesn't print a new hunk header; it just runs the hunks 1.51 +together, with a few lines of context between modifications. 1.52 + 1.53 +Each line of context begins with a space character. Within the hunk, 1.54 +a line that begins with ``\texttt{-}'' means ``remove this line,'' 1.55 +while a line that begins with ``\texttt{+}'' means ``insert this 1.56 +line.'' For example, a line that is modified is represented by one 1.57 +deletion and one insertion. 1.58 + 1.59 +We will return to ome of the more subtle aspects of patches later (in 1.60 +section~\ref{ex:mq:adv-patch}), but you should have enough information 1.61 +now to use MQ. 1.62 + 1.63 \section{Getting started with Mercurial Queues} 1.64 \label{sec:mq:start} 1.65 1.66 @@ -200,6 +256,7 @@ 1.67 working directory as you usually would. All of the normal Mercurial 1.68 commands, such as \hgcmd{diff} and \hgcmd{annotate}, work exactly as 1.69 they did before. 1.70 + 1.71 \subsection{Refreshing a patch} 1.72 1.73 When you reach a point where you want to save your work, use the 1.74 @@ -319,45 +376,12 @@ 1.75 \hgcmd{qrefresh} the core patch, and \hgcmd{qpush} back to the UI 1.76 patch to continue where you left off. 1.77 1.78 -\section{Mercurial Queues and GNU patch} 1.79 -\label{sec:mq:patch} 1.80 - 1.81 -MQ uses the GNU \command{patch} command to apply patches. Because MQ 1.82 -doesn't hide its patch-oriented nature, it is helpful to understand 1.83 -the data that MQ and \command{patch} work with, and a few aspects of 1.84 -how \command{patch} operates. 1.85 - 1.86 -The \command{diff} command generates a list of modifications by 1.87 -comparing two files. The \command{patch} command applies a list of 1.88 -modifications to a file. The kinds of files that \command{diff} and 1.89 -\command{patch} work with are referred to as both ``diffs'' and 1.90 -``patches;'' there is no difference between a diff and a patch. 1.91 - 1.92 -A patch file can start with arbitrary text; MQ uses this text as the 1.93 -commit message when creating changesets. It treats the first line 1.94 -that starts with the string ``\texttt{diff~-}'' as the separator 1.95 -between header and content. 1.96 - 1.97 -MQ works with \emph{unified} diffs (\command{patch} can accept several 1.98 -other diff formats, but MQ doesn't). A unified diff contains two 1.99 -kinds of header. The \emph{file header} describes the file being 1.100 -modified; it contains the name of the file to modify. When 1.101 -\command{patch} sees a new file header, it looks for a file with that 1.102 -name to start modifying. 1.103 - 1.104 -After the file header comes a series of \emph{hunks}. Each hunk 1.105 -starts with a header; this identifies the range of line numbers within 1.106 -the file that the hunk should modify. Following the header, a hunk 1.107 -starts and ends with a few (usually three) lines of text from the 1.108 -unmodified file; these are called the \emph{context} for the hunk. 1.109 -Each unmodified line begins with a space characters. Within the hunk, 1.110 -a line that begins with ``\texttt{-}'' means ``remove this line,'' 1.111 -while a line that begins with ``\texttt{+}'' means ``insert this 1.112 -line.'' For example, a line that is modified is represented by one 1.113 -deletion and one insertion. 1.114 - 1.115 -The \command{diff} command runs hunks together when there's not enough 1.116 -context between modifications to justify 1.117 +\section{More about patches} 1.118 +\label{sec:mq:adv-patch} 1.119 + 1.120 +MQ uses the GNU \command{patch} command to apply patches, so it's 1.121 +helpful to know about a few more detailed aspects of how 1.122 +\command{patch} works. 1.123 1.124 When \command{patch} applies a hunk, it tries a handful of 1.125 successively less accurate strategies to try to make the hunk apply. 1.126 @@ -622,6 +646,7 @@ 1.127 confuse MQ's idea of which patches are applied. 1.128 1.129 \section{Commands for working with patches} 1.130 +\label{sec:mq:tools} 1.131 1.132 Once you've been working with patches for a while, you'll find 1.133 yourself hungry for tools that will help you to understand and 1.134 @@ -636,6 +661,12 @@ 1.135 do clever things with prefixes of file names that inevitably confuse 1.136 at least me.) 1.137 1.138 +\begin{figure}[ht] 1.139 + \interaction{mq.tools.tools} 1.140 + \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands} 1.141 + \label{ex:mq:tools} 1.142 +\end{figure} 1.143 + 1.144 The \package{patchutils} package~\cite{web:patchutils} is invaluable. 1.145 It provides a set of small utilities that follow the ``Unix 1.146 philosophy;'' each does one useful thing with a patch. The 1.147 @@ -645,6 +676,122 @@ 1.148 invocation of \command{filterdiff} can generate a smaller patch that 1.149 only touches files whose names match a particular glob pattern. 1.150 1.151 +\section{Good ways to work with patches} 1.152 + 1.153 +Whether you are working on a patch series to submit to a free software 1.154 +or open source project, or a series that you intend to treat as a 1.155 +sequence of regular changesets when you're done, you can use some 1.156 +simple techniques to keep your work well organised. 1.157 + 1.158 +Give your patches descriptive names. A good name for a patch might be 1.159 +\filename{rework-device-alloc.patch}, because it will immediately give 1.160 +you a hint what the purpose of the patch is. Long names shouldn't be 1.161 +a problem; you won't be typing the names often, but you \emph{will} be 1.162 +running commands like \hgcmd{qapplied} and \hgcmd{qtop} over and over. 1.163 +Good naming becomes especially important when you have a number of 1.164 +patches to work with, or if you are juggling a number of different 1.165 +tasks and your patches only get a fraction of your attention. 1.166 + 1.167 +Be aware of what patch you're working on. Use the \hgcmd{qtop} 1.168 +command and skim over the text of your patches frequently---for 1.169 +example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where 1.170 +you stand. I have several times worked on and \hgcmd{qrefresh}ed a 1.171 +patch other than the one I intended, and it's often tricky to migrate 1.172 +changes into the right patch after making them in the wrong one. 1.173 + 1.174 +For this reason, it is very much worth investing a little time to 1.175 +learn how to use some of the third-party tools I described in 1.176 +section~\ref{sec:mq:tools}, particularly \command{diffstat} and 1.177 +\command{filterdiff}. The former will give you a quick idea of what 1.178 +changes your patch is making, while the latter makes it easy to splice 1.179 +hunks selectively out of one patch and into another. 1.180 + 1.181 +\section{MQ cookbook} 1.182 + 1.183 +\subsection{Manage ``trivial'' patches} 1.184 + 1.185 +Because the overhead of dropping files into a new Mercurial repository 1.186 +is so low, it makes a lot of sense to manage patches this way even if 1.187 +you simply want to make a few changes to a source tarball that you 1.188 +downloaded. 1.189 + 1.190 +Begin by downloading and unpacking the source tarball, 1.191 +and turning it into a Mercurial repository. 1.192 +\interaction{mq.tarball.download} 1.193 + 1.194 +Continue by creating a patch stack and making your changes. 1.195 +\interaction{mq.tarball.qinit} 1.196 + 1.197 +Let's say a few weeks or months pass, and your package author releases 1.198 +a new version. First, bring their changes into the repository. 1.199 +\interaction{mq.tarball.newsource} 1.200 +The pipeline starting with \hgcmd{locate} above deletes all files in 1.201 +the working directory, so that \hgcmd{commit}'s 1.202 +\hgopt{commit}{--addremove} option can actually tell which files have 1.203 +really been removed in the newer version of the source. 1.204 + 1.205 +Finally, you can apply your patches on top of the new tree. 1.206 +\interaction{mq.tarball.repush} 1.207 + 1.208 +\subsection{Combining entire patches} 1.209 +\label{sec:mq:combine} 1.210 + 1.211 +It's easy to combine entire patches. 1.212 + 1.213 +\begin{enumerate} 1.214 +\item \hgcmd{qpop} your applied patches until neither patch is 1.215 + applied. 1.216 +\item Concatenate the patches that you want to combine together: 1.217 + \begin{codesample4} 1.218 + cat patch-to-drop.patch >> patch-to-augment.patch 1.219 + \end{codesample4} 1.220 + The description from the first patch (if you have one) will be used 1.221 + as the commit comment when you \hgcmd{qpush} the combined patch. 1.222 + Edit the patch description if you need to. 1.223 +\item Use the \hgcmd{qdel} command to delete the patch you're dropping 1.224 + from the \sfilename{series} file. 1.225 +\item \hgcmd{qpush} the combined patch. Fix up any rejects. 1.226 +\item \hgcmd{qrefresh} the combined patch to tidy it up. 1.227 +\end{enumerate} 1.228 + 1.229 +\subsection{Merging part of one patch into another} 1.230 + 1.231 +Merging \emph{part} of one patch into another is more difficult than 1.232 +combining entire patches. 1.233 + 1.234 +If you want to move changes to entire files, you can use 1.235 +\command{filterdiff}'s \cmdopt{filterdiff}{-i} and 1.236 +\cmdopt{filterdiff}{-x} options to choose the modifications to snip 1.237 +out of one patch, concatenating its output onto the end of the patch 1.238 +you want to merge into. You usually won't need to modify the patch 1.239 +you've merged the changes from. Instead, MQ will report some rejected 1.240 +hunks when you \hgcmd{qpush} it (from the hunks you moved into the 1.241 +other patch), and you can simply \hgcmd{qrefresh} the patch to drop 1.242 +the duplicate hunks. 1.243 + 1.244 +If you have a patch that has multiple hunks modifying a file, and you 1.245 +only want to move a few of those hunks, the job becomes more messy, 1.246 +but you can still partly automate it. Use \cmdargs{lsdiff}{-nvv} to 1.247 +print some metadata about the patch. 1.248 +\interaction{mq.tools.lsdiff} 1.249 + 1.250 +This command prints three different kinds of number: 1.251 +\begin{itemize} 1.252 +\item a \emph{file number} to identify each file modified in the patch; 1.253 +\item the line number within a modified file that a hunk starts at; and 1.254 +\item a \emph{hunk number} to identify that hunk. 1.255 +\end{itemize} 1.256 + 1.257 +You'll have to use some visual inspection, and reading of the patch, 1.258 +to identify the file and hunk numbers you'll want, but you can then 1.259 +pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files} 1.260 +and \cmdopt{filterdiff}{--hunks} options, to select exactly the file 1.261 +and hunk you want to extract. 1.262 + 1.263 +Once you have this hunk, you can concatenate it onto the end of your 1.264 +destination patch and continue with the remainder of 1.265 +section~\ref{sec:mq:combine}. 1.266 + 1.267 %%% Local Variables: 1.268 %%% mode: latex 1.269 %%% TeX-master: "00book"