rev |
line source |
belaran@964
|
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
|
belaran@964
|
2
|
belaran@964
|
3 <chapter>
|
belaran@964
|
4 <title>Managing change with Mercurial Queues</title>
|
belaran@964
|
5 <para>\label{chap:mq}</para>
|
belaran@964
|
6
|
belaran@964
|
7 <sect1>
|
belaran@964
|
8 <title>The patch management problem</title>
|
belaran@964
|
9 <para>\label{sec:mq:patch-mgmt}</para>
|
belaran@964
|
10
|
belaran@964
|
11 <para>Here is a common scenario: you need to install a software package from
|
belaran@964
|
12 source, but you find a bug that you must fix in the source before you
|
belaran@964
|
13 can start using the package. You make your changes, forget about the
|
belaran@964
|
14 package for a while, and a few months later you need to upgrade to a
|
belaran@964
|
15 newer version of the package. If the newer version of the package
|
belaran@964
|
16 still has the bug, you must extract your fix from the older source
|
belaran@964
|
17 tree and apply it against the newer version. This is a tedious task,
|
belaran@964
|
18 and it's easy to make mistakes.</para>
|
belaran@964
|
19
|
belaran@964
|
20 <para>This is a simple case of the <quote>patch management</quote> problem. You have
|
belaran@964
|
21 an <quote>upstream</quote> source tree that you can't change; you need to make
|
belaran@964
|
22 some local changes on top of the upstream tree; and you'd like to be
|
belaran@964
|
23 able to keep those changes separate, so that you can apply them to
|
belaran@964
|
24 newer versions of the upstream source.</para>
|
belaran@964
|
25
|
belaran@964
|
26 <para>The patch management problem arises in many situations. Probably the
|
belaran@964
|
27 most visible is that a user of an open source software project will
|
belaran@964
|
28 contribute a bug fix or new feature to the project's maintainers in the
|
belaran@964
|
29 form of a patch.</para>
|
belaran@964
|
30
|
belaran@964
|
31 <para>Distributors of operating systems that include open source software
|
belaran@964
|
32 often need to make changes to the packages they distribute so that
|
belaran@964
|
33 they will build properly in their environments.</para>
|
belaran@964
|
34
|
belaran@964
|
35 <para>When you have few changes to maintain, it is easy to manage a single
|
belaran@964
|
36 patch using the standard <command>diff</command> and <command>patch</command> programs
|
belaran@964
|
37 (see section <xref linkend="sec:mq:patch"/> for a discussion of these tools).
|
belaran@964
|
38 Once the number of changes grows, it starts to make sense to maintain
|
belaran@964
|
39 patches as discrete <quote>chunks of work,</quote> so that for example a single
|
belaran@964
|
40 patch will contain only one bug fix (the patch might modify several
|
belaran@964
|
41 files, but it's doing <quote>only one thing</quote>), and you may have a number
|
belaran@964
|
42 of such patches for different bugs you need fixed and local changes
|
belaran@964
|
43 you require. In this situation, if you submit a bug fix patch to the
|
belaran@964
|
44 upstream maintainers of a package and they include your fix in a
|
belaran@964
|
45 subsequent release, you can simply drop that single patch when you're
|
belaran@964
|
46 updating to the newer release.</para>
|
belaran@964
|
47
|
belaran@964
|
48 <para>Maintaining a single patch against an upstream tree is a little
|
belaran@964
|
49 tedious and error-prone, but not difficult. However, the complexity
|
belaran@964
|
50 of the problem grows rapidly as the number of patches you have to
|
belaran@964
|
51 maintain increases. With more than a tiny number of patches in hand,
|
belaran@964
|
52 understanding which ones you have applied and maintaining them moves
|
belaran@964
|
53 from messy to overwhelming.</para>
|
belaran@964
|
54
|
belaran@964
|
55 <para>Fortunately, Mercurial includes a powerful extension, Mercurial Queues
|
belaran@964
|
56 (or simply <quote>MQ</quote>), that massively simplifies the patch management
|
belaran@964
|
57 problem.
|
belaran@964
|
58 </para>
|
belaran@964
|
59
|
belaran@964
|
60 </sect1>
|
belaran@964
|
61 <sect1>
|
belaran@964
|
62 <title>The prehistory of Mercurial Queues</title>
|
belaran@964
|
63 <para>\label{sec:mq:history}
|
belaran@964
|
64 </para>
|
belaran@964
|
65
|
belaran@964
|
66 <para>During the late 1990s, several Linux kernel developers started to
|
belaran@964
|
67 maintain <quote>patch series</quote> that modified the behaviour of the Linux
|
belaran@964
|
68 kernel. Some of these series were focused on stability, some on
|
belaran@964
|
69 feature coverage, and others were more speculative.
|
belaran@964
|
70 </para>
|
belaran@964
|
71
|
belaran@964
|
72 <para>The sizes of these patch series grew rapidly. In 2002, Andrew Morton
|
belaran@964
|
73 published some shell scripts he had been using to automate the task of
|
belaran@964
|
74 managing his patch queues. Andrew was successfully using these
|
belaran@964
|
75 scripts to manage hundreds (sometimes thousands) of patches on top of
|
belaran@964
|
76 the Linux kernel.
|
belaran@964
|
77 </para>
|
belaran@964
|
78
|
belaran@964
|
79 <sect2>
|
belaran@964
|
80 <title>A patchwork quilt</title>
|
belaran@964
|
81 <para>\label{sec:mq:quilt}
|
belaran@964
|
82 </para>
|
belaran@964
|
83
|
belaran@964
|
84 <para>In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the
|
belaran@964
|
85 approach of Andrew's scripts and published a tool called <quote>patchwork
|
belaran@964
|
86 quilt</quote> <citation>web:quilt</citation>, or simply <quote>quilt</quote>
|
belaran@964
|
87 (see <citation>gruenbacher:2005</citation> for a paper describing it). Because
|
belaran@964
|
88 quilt substantially automated patch management, it rapidly gained a
|
belaran@964
|
89 large following among open source software developers.
|
belaran@964
|
90 </para>
|
belaran@964
|
91
|
belaran@964
|
92 <para>Quilt manages a <emphasis>stack of patches</emphasis> on top of a directory tree.
|
belaran@964
|
93 To begin, you tell quilt to manage a directory tree, and tell it which
|
belaran@964
|
94 files you want to manage; it stores away the names and contents of
|
belaran@964
|
95 those files. To fix a bug, you create a new patch (using a single
|
belaran@964
|
96 command), edit the files you need to fix, then <quote>refresh</quote> the patch.
|
belaran@964
|
97 </para>
|
belaran@964
|
98
|
belaran@964
|
99 <para>The refresh step causes quilt to scan the directory tree; it updates
|
belaran@964
|
100 the patch with all of the changes you have made. You can create
|
belaran@964
|
101 another patch on top of the first, which will track the changes
|
belaran@964
|
102 required to modify the tree from <quote>tree with one patch applied</quote> to
|
belaran@964
|
103 <quote>tree with two patches applied</quote>.
|
belaran@964
|
104 </para>
|
belaran@964
|
105
|
belaran@964
|
106 <para>You can <emphasis>change</emphasis> which patches are applied to the tree. If you
|
belaran@964
|
107 <quote>pop</quote> a patch, the changes made by that patch will vanish from the
|
belaran@964
|
108 directory tree. Quilt remembers which patches you have popped,
|
belaran@964
|
109 though, so you can <quote>push</quote> a popped patch again, and the directory
|
belaran@964
|
110 tree will be restored to contain the modifications in the patch. Most
|
belaran@964
|
111 importantly, you can run the <quote>refresh</quote> command at any time, and the
|
belaran@964
|
112 topmost applied patch will be updated. This means that you can, at
|
belaran@964
|
113 any time, change both which patches are applied and what
|
belaran@964
|
114 modifications those patches make.
|
belaran@964
|
115 </para>
|
belaran@964
|
116
|
belaran@964
|
117 <para>Quilt knows nothing about revision control tools, so it works equally
|
belaran@964
|
118 well on top of an unpacked tarball or a Subversion working copy.
|
belaran@964
|
119 </para>
|
belaran@964
|
120
|
belaran@964
|
121 </sect2>
|
belaran@964
|
122 <sect2>
|
belaran@964
|
123 <title>From patchwork quilt to Mercurial Queues</title>
|
belaran@964
|
124 <para>\label{sec:mq:quilt-mq}
|
belaran@964
|
125 </para>
|
belaran@964
|
126
|
belaran@964
|
127 <para>In mid-2005, Chris Mason took the features of quilt and wrote an
|
belaran@964
|
128 extension that he called Mercurial Queues, which added quilt-like
|
belaran@964
|
129 behaviour to Mercurial.
|
belaran@964
|
130 </para>
|
belaran@964
|
131
|
belaran@964
|
132 <para>The key difference between quilt and MQ is that quilt knows nothing
|
belaran@964
|
133 about revision control systems, while MQ is <emphasis>integrated</emphasis> into
|
belaran@964
|
134 Mercurial. Each patch that you push is represented as a Mercurial
|
belaran@964
|
135 changeset. Pop a patch, and the changeset goes away.
|
belaran@964
|
136 </para>
|
belaran@964
|
137
|
belaran@964
|
138 <para>Because quilt does not care about revision control tools, it is still
|
belaran@964
|
139 a tremendously useful piece of software to know about for situations
|
belaran@964
|
140 where you cannot use Mercurial and MQ.
|
belaran@964
|
141 </para>
|
belaran@964
|
142
|
belaran@964
|
143 </sect2>
|
belaran@964
|
144 </sect1>
|
belaran@964
|
145 <sect1>
|
belaran@964
|
146 <title>The huge advantage of MQ</title>
|
belaran@964
|
147
|
belaran@964
|
148 <para>I cannot overstate the value that MQ offers through the unification of
|
belaran@964
|
149 patches and revision control.
|
belaran@964
|
150 </para>
|
belaran@964
|
151
|
belaran@964
|
152 <para>A major reason that patches have persisted in the free software and
|
belaran@964
|
153 open source world&emdash;in spite of the availability of increasingly
|
belaran@964
|
154 capable revision control tools over the years&emdash;is the <emphasis>agility</emphasis>
|
belaran@964
|
155 they offer.
|
belaran@964
|
156 </para>
|
belaran@964
|
157
|
belaran@964
|
158 <para>Traditional revision control tools make a permanent, irreversible
|
belaran@964
|
159 record of everything that you do. While this has great value, it's
|
belaran@964
|
160 also somewhat stifling. If you want to perform a wild-eyed
|
belaran@964
|
161 experiment, you have to be careful in how you go about it, or you risk
|
belaran@964
|
162 leaving unneeded&emdash;or worse, misleading or destabilising&emdash;traces of
|
belaran@964
|
163 your missteps and errors in the permanent revision record.
|
belaran@964
|
164 </para>
|
belaran@964
|
165
|
belaran@964
|
166 <para>By contrast, MQ's marriage of distributed revision control with
|
belaran@964
|
167 patches makes it much easier to isolate your work. Your patches live
|
belaran@964
|
168 on top of normal revision history, and you can make them disappear or
|
belaran@964
|
169 reappear at will. If you don't like a patch, you can drop it. If a
|
belaran@964
|
170 patch isn't quite as you want it to be, simply fix it&emdash;as many times
|
belaran@964
|
171 as you need to, until you have refined it into the form you desire.
|
belaran@964
|
172 </para>
|
belaran@964
|
173
|
belaran@964
|
174 <para>As an example, the integration of patches with revision control makes
|
belaran@964
|
175 understanding patches and debugging their effects&emdash;and their
|
belaran@964
|
176 interplay with the code they're based on&emdash;<emphasis>enormously</emphasis> easier.
|
belaran@964
|
177 Since every applied patch has an associated changeset, you can use
|
belaran@964
|
178 <command role="hg-cmd">hg log <emphasis>filename</emphasis></command> to see which changesets and patches
|
belaran@964
|
179 affected a file. You can use the <literal role="hg-ext">bisect</literal> command to
|
belaran@964
|
180 binary-search through all changesets and applied patches to see where
|
belaran@964
|
181 a bug got introduced or fixed. You can use the <command role="hg-cmd">hg annotate</command>
|
belaran@964
|
182 command to see which changeset or patch modified a particular line of
|
belaran@964
|
183 a source file. And so on.
|
belaran@964
|
184 </para>
|
belaran@964
|
185
|
belaran@964
|
186 </sect1>
|
belaran@964
|
187 <sect1>
|
belaran@964
|
188 <title>Understanding patches</title>
|
belaran@964
|
189 <para>\label{sec:mq:patch}
|
belaran@964
|
190 </para>
|
belaran@964
|
191
|
belaran@964
|
192 <para>Because MQ doesn't hide its patch-oriented nature, it is helpful to
|
belaran@964
|
193 understand what patches are, and a little about the tools that work
|
belaran@964
|
194 with them.
|
belaran@964
|
195 </para>
|
belaran@964
|
196
|
belaran@964
|
197 <para>The traditional Unix <command>diff</command> command compares two files, and
|
belaran@964
|
198 prints a list of differences between them. The <command>patch</command> command
|
belaran@964
|
199 understands these differences as <emphasis>modifications</emphasis> to make to a
|
belaran@964
|
200 file. Take a look at figure <xref linkend="ex:mq:diff"/> for a simple example of
|
belaran@964
|
201 these commands in action.
|
belaran@964
|
202 </para>
|
belaran@964
|
203
|
belaran@964
|
204 <informalfigure>
|
belaran@964
|
205 <para> <!-- &interaction.mq.dodiff.diff; -->
|
belaran@964
|
206 <caption><para>Simple uses of the <command>diff</para></caption> and \command{patch</command> commands}
|
belaran@964
|
207 \label{ex:mq:diff}
|
belaran@964
|
208 </para>
|
belaran@964
|
209 </informalfigure>
|
belaran@964
|
210
|
belaran@964
|
211 <para>The type of file that <command>diff</command> generates (and <command>patch</command>
|
belaran@964
|
212 takes as input) is called a <quote>patch</quote> or a <quote>diff</quote>; there is no
|
belaran@964
|
213 difference between a patch and a diff. (We'll use the term <quote>patch</quote>,
|
belaran@964
|
214 since it's more commonly used.)
|
belaran@964
|
215 </para>
|
belaran@964
|
216
|
belaran@964
|
217 <para>A patch file can start with arbitrary text; the <command>patch</command>
|
belaran@964
|
218 command ignores this text, but MQ uses it as the commit message when
|
belaran@964
|
219 creating changesets. To find the beginning of the patch content,
|
belaran@964
|
220 <command>patch</command> searches for the first line that starts with the
|
belaran@964
|
221 string <quote><literal>diff -</literal></quote>.
|
belaran@964
|
222 </para>
|
belaran@964
|
223
|
belaran@964
|
224 <para>MQ works with <emphasis>unified</emphasis> diffs (<command>patch</command> can accept several
|
belaran@964
|
225 other diff formats, but MQ doesn't). A unified diff contains two
|
belaran@964
|
226 kinds of header. The <emphasis>file header</emphasis> describes the file being
|
belaran@964
|
227 modified; it contains the name of the file to modify. When
|
belaran@964
|
228 <command>patch</command> sees a new file header, it looks for a file with that
|
belaran@964
|
229 name to start modifying.
|
belaran@964
|
230 </para>
|
belaran@964
|
231
|
belaran@964
|
232 <para>After the file header comes a series of <emphasis>hunks</emphasis>. Each hunk
|
belaran@964
|
233 starts with a header; this identifies the range of line numbers within
|
belaran@964
|
234 the file that the hunk should modify. Following the header, a hunk
|
belaran@964
|
235 starts and ends with a few (usually three) lines of text from the
|
belaran@964
|
236 unmodified file; these are called the <emphasis>context</emphasis> for the hunk. If
|
belaran@964
|
237 there's only a small amount of context between successive hunks,
|
belaran@964
|
238 <command>diff</command> doesn't print a new hunk header; it just runs the hunks
|
belaran@964
|
239 together, with a few lines of context between modifications.
|
belaran@964
|
240 </para>
|
belaran@964
|
241
|
belaran@964
|
242 <para>Each line of context begins with a space character. Within the hunk,
|
belaran@964
|
243 a line that begins with <quote><literal>-</literal></quote> means <quote>remove this line,</quote>
|
belaran@964
|
244 while a line that begins with <quote><literal>+</literal></quote> means <quote>insert this
|
belaran@964
|
245 line.</quote> For example, a line that is modified is represented by one
|
belaran@964
|
246 deletion and one insertion.
|
belaran@964
|
247 </para>
|
belaran@964
|
248
|
belaran@964
|
249 <para>We will return to some of the more subtle aspects of patches later (in
|
belaran@964
|
250 section <xref linkend="sec:mq:adv-patch"/>), but you should have enough information
|
belaran@964
|
251 now to use MQ.
|
belaran@964
|
252 </para>
|
belaran@964
|
253
|
belaran@964
|
254 </sect1>
|
belaran@964
|
255 <sect1>
|
belaran@964
|
256 <title>Getting started with Mercurial Queues</title>
|
belaran@964
|
257 <para>\label{sec:mq:start}
|
belaran@964
|
258 </para>
|
belaran@964
|
259
|
belaran@964
|
260 <para>Because MQ is implemented as an extension, you must explicitly enable
|
belaran@964
|
261 before you can use it. (You don't need to download anything; MQ ships
|
belaran@964
|
262 with the standard Mercurial distribution.) To enable MQ, edit your
|
belaran@964
|
263 <filename role="home">~/.hgrc</filename> file, and add the lines in figure <xref linkend="ex:mq:config"/>.
|
belaran@964
|
264 </para>
|
belaran@964
|
265
|
belaran@964
|
266 <informalfigure>
|
belaran@964
|
267 <programlisting>
|
belaran@964
|
268 <para> [extensions]
|
belaran@964
|
269 hgext.mq =
|
belaran@964
|
270 </para>
|
belaran@964
|
271 </programlisting>
|
belaran@964
|
272 <para> \label{ex:mq:config}
|
belaran@964
|
273 <caption><para>Contents to add to <filename role="home">~/.hgrc</para></caption> to enable the MQ extension</filename>
|
belaran@964
|
274 </para>
|
belaran@964
|
275 </informalfigure>
|
belaran@964
|
276
|
belaran@964
|
277 <para>Once the extension is enabled, it will make a number of new commands
|
belaran@964
|
278 available. To verify that the extension is working, you can use
|
belaran@964
|
279 <command role="hg-cmd">hg help</command> to see if the <command role="hg-ext-mq">qinit</command> command is now available; see
|
belaran@964
|
280 the example in figure <xref linkend="ex:mq:enabled"/>.
|
belaran@964
|
281 </para>
|
belaran@964
|
282
|
belaran@964
|
283 <informalfigure>
|
belaran@964
|
284 <para> <!-- &interaction.mq.qinit-help.help; -->
|
belaran@964
|
285 <caption><para>How to verify that MQ is enabled</para></caption>
|
belaran@964
|
286 \label{ex:mq:enabled}
|
belaran@964
|
287 </para>
|
belaran@964
|
288 </informalfigure>
|
belaran@964
|
289
|
belaran@964
|
290 <para>You can use MQ with <emphasis>any</emphasis> Mercurial repository, and its commands
|
belaran@964
|
291 only operate within that repository. To get started, simply prepare
|
belaran@964
|
292 the repository using the <command role="hg-ext-mq">qinit</command> command (see
|
belaran@964
|
293 figure <xref linkend="ex:mq:qinit"/>). This command creates an empty directory
|
belaran@964
|
294 called <filename role="special" class="directory">.hg/patches</filename>, where MQ will keep its metadata. As
|
belaran@964
|
295 with many Mercurial commands, the <command role="hg-ext-mq">qinit</command> command prints nothing
|
belaran@964
|
296 if it succeeds.
|
belaran@964
|
297 </para>
|
belaran@964
|
298
|
belaran@964
|
299 <informalfigure>
|
belaran@964
|
300 <para> <!-- &interaction.mq.tutorial.qinit; -->
|
belaran@964
|
301 <caption><para>Preparing a repository for use with MQ</para></caption>
|
belaran@964
|
302 \label{ex:mq:qinit}
|
belaran@964
|
303 </para>
|
belaran@964
|
304 </informalfigure>
|
belaran@964
|
305
|
belaran@964
|
306 <informalfigure>
|
belaran@964
|
307 <para> <!-- &interaction.mq.tutorial.qnew; -->
|
belaran@964
|
308 <caption><para>Creating a new patch</para></caption>
|
belaran@964
|
309 \label{ex:mq:qnew}
|
belaran@964
|
310 </para>
|
belaran@964
|
311 </informalfigure>
|
belaran@964
|
312
|
belaran@964
|
313 <sect2>
|
belaran@964
|
314 <title>Creating a new patch</title>
|
belaran@964
|
315
|
belaran@964
|
316 <para>To begin work on a new patch, use the <command role="hg-ext-mq">qnew</command> command. This
|
belaran@964
|
317 command takes one argument, the name of the patch to create. MQ will
|
belaran@964
|
318 use this as the name of an actual file in the <filename role="special" class="directory">.hg/patches</filename>
|
belaran@964
|
319 directory, as you can see in figure <xref linkend="ex:mq:qnew"/>.
|
belaran@964
|
320 </para>
|
belaran@964
|
321
|
belaran@964
|
322 <para>Also newly present in the <filename role="special" class="directory">.hg/patches</filename> directory are two
|
belaran@964
|
323 other files, <filename role="special">series</filename> and <filename role="special">status</filename>. The
|
belaran@964
|
324 <filename role="special">series</filename> file lists all of the patches that MQ knows about
|
belaran@964
|
325 for this repository, with one patch per line. Mercurial uses the
|
belaran@964
|
326 <filename role="special">status</filename> file for internal book-keeping; it tracks all of the
|
belaran@964
|
327 patches that MQ has <emphasis>applied</emphasis> in this repository.
|
belaran@964
|
328 </para>
|
belaran@964
|
329
|
belaran@964
|
330 <note>
|
belaran@964
|
331 <para> You may sometimes want to edit the <filename role="special">series</filename> file by hand;
|
belaran@964
|
332 for example, to change the sequence in which some patches are
|
belaran@964
|
333 applied. However, manually editing the <filename role="special">status</filename> file is
|
belaran@964
|
334 almost always a bad idea, as it's easy to corrupt MQ's idea of what
|
belaran@964
|
335 is happening.
|
belaran@964
|
336 </para>
|
belaran@964
|
337 </note>
|
belaran@964
|
338
|
belaran@964
|
339 <para>Once you have created your new patch, you can edit files in the
|
belaran@964
|
340 working directory as you usually would. All of the normal Mercurial
|
belaran@964
|
341 commands, such as <command role="hg-cmd">hg diff</command> and <command role="hg-cmd">hg annotate</command>, work exactly as
|
belaran@964
|
342 they did before.
|
belaran@964
|
343 </para>
|
belaran@964
|
344
|
belaran@964
|
345 </sect2>
|
belaran@964
|
346 <sect2>
|
belaran@964
|
347 <title>Refreshing a patch</title>
|
belaran@964
|
348
|
belaran@964
|
349 <para>When you reach a point where you want to save your work, use the
|
belaran@964
|
350 <command role="hg-ext-mq">qrefresh</command> command (figure <xref linkend="ex:mq:qnew"/>) to update the patch
|
belaran@964
|
351 you are working on. This command folds the changes you have made in
|
belaran@964
|
352 the working directory into your patch, and updates its corresponding
|
belaran@964
|
353 changeset to contain those changes.
|
belaran@964
|
354 </para>
|
belaran@964
|
355
|
belaran@964
|
356 <informalfigure>
|
belaran@964
|
357 <para> <!-- &interaction.mq.tutorial.qrefresh; -->
|
belaran@964
|
358 <caption><para>Refreshing a patch</para></caption>
|
belaran@964
|
359 \label{ex:mq:qrefresh}
|
belaran@964
|
360 </para>
|
belaran@964
|
361 </informalfigure>
|
belaran@964
|
362
|
belaran@964
|
363 <para>You can run <command role="hg-ext-mq">qrefresh</command> as often as you like, so it's a good way
|
belaran@964
|
364 to <quote>checkpoint</quote> your work. Refresh your patch at an opportune
|
belaran@964
|
365 time; try an experiment; and if the experiment doesn't work out,
|
belaran@964
|
366 <command role="hg-cmd">hg revert</command> your modifications back to the last time you refreshed.
|
belaran@964
|
367 </para>
|
belaran@964
|
368
|
belaran@964
|
369 <informalfigure>
|
belaran@964
|
370 <para> <!-- &interaction.mq.tutorial.qrefresh2; -->
|
belaran@964
|
371 <caption><para>Refresh a patch many times to accumulate changes</para></caption>
|
belaran@964
|
372 \label{ex:mq:qrefresh2}
|
belaran@964
|
373 </para>
|
belaran@964
|
374 </informalfigure>
|
belaran@964
|
375
|
belaran@964
|
376 </sect2>
|
belaran@964
|
377 <sect2>
|
belaran@964
|
378 <title>Stacking and tracking patches</title>
|
belaran@964
|
379
|
belaran@964
|
380 <para>Once you have finished working on a patch, or need to work on another,
|
belaran@964
|
381 you can use the <command role="hg-ext-mq">qnew</command> command again to create a new patch.
|
belaran@964
|
382 Mercurial will apply this patch on top of your existing patch. See
|
belaran@964
|
383 figure <xref linkend="ex:mq:qnew2"/> for an example. Notice that the patch
|
belaran@964
|
384 contains the changes in our prior patch as part of its context (you
|
belaran@964
|
385 can see this more clearly in the output of <command role="hg-cmd">hg annotate</command>).
|
belaran@964
|
386 </para>
|
belaran@964
|
387
|
belaran@964
|
388 <informalfigure>
|
belaran@964
|
389 <para> <!-- &interaction.mq.tutorial.qnew2; -->
|
belaran@964
|
390 <caption><para>Stacking a second patch on top of the first</para></caption>
|
belaran@964
|
391 \label{ex:mq:qnew2}
|
belaran@964
|
392 </para>
|
belaran@964
|
393 </informalfigure>
|
belaran@964
|
394
|
belaran@964
|
395 <para>So far, with the exception of <command role="hg-ext-mq">qnew</command> and <command role="hg-ext-mq">qrefresh</command>, we've
|
belaran@964
|
396 been careful to only use regular Mercurial commands. However, MQ
|
belaran@964
|
397 provides many commands that are easier to use when you are thinking
|
belaran@964
|
398 about patches, as illustrated in figure <xref linkend="ex:mq:qseries"/>:
|
belaran@964
|
399 </para>
|
belaran@964
|
400
|
belaran@964
|
401 <itemizedlist>
|
belaran@964
|
402 <listitem><para>The <command role="hg-ext-mq">qseries</command> command lists every patch that MQ knows
|
belaran@964
|
403 about in this repository, from oldest to newest (most recently
|
belaran@964
|
404 <emphasis>created</emphasis>).
|
belaran@964
|
405 </para>
|
belaran@964
|
406 </listitem>
|
belaran@964
|
407 <listitem><para>The <command role="hg-ext-mq">qapplied</command> command lists every patch that MQ has
|
belaran@964
|
408 <emphasis>applied</emphasis> in this repository, again from oldest to newest (most
|
belaran@964
|
409 recently applied).
|
belaran@964
|
410 </para>
|
belaran@964
|
411 </listitem></itemizedlist>
|
belaran@964
|
412
|
belaran@964
|
413 <informalfigure>
|
belaran@964
|
414 <para> <!-- &interaction.mq.tutorial.qseries; -->
|
belaran@964
|
415 \caption{Understanding the patch stack with <command role="hg-ext-mq">qseries</command> and
|
belaran@964
|
416 <command role="hg-ext-mq">qapplied</command>}
|
belaran@964
|
417 \label{ex:mq:qseries}
|
belaran@964
|
418 </para>
|
belaran@964
|
419 </informalfigure>
|
belaran@964
|
420
|
belaran@964
|
421 </sect2>
|
belaran@964
|
422 <sect2>
|
belaran@964
|
423 <title>Manipulating the patch stack</title>
|
belaran@964
|
424
|
belaran@964
|
425 <para>The previous discussion implied that there must be a difference
|
belaran@964
|
426 between <quote>known</quote> and <quote>applied</quote> patches, and there is. MQ can
|
belaran@964
|
427 manage a patch without it being applied in the repository.
|
belaran@964
|
428 </para>
|
belaran@964
|
429
|
belaran@964
|
430 <para>An <emphasis>applied</emphasis> patch has a corresponding changeset in the
|
belaran@964
|
431 repository, and the effects of the patch and changeset are visible in
|
belaran@964
|
432 the working directory. You can undo the application of a patch using
|
belaran@964
|
433 the <command role="hg-ext-mq">qpop</command> command. MQ still <emphasis>knows about</emphasis>, or manages, a
|
belaran@964
|
434 popped patch, but the patch no longer has a corresponding changeset in
|
belaran@964
|
435 the repository, and the working directory does not contain the changes
|
belaran@964
|
436 made by the patch. Figure <xref linkend="fig:mq:stack"/> illustrates the
|
belaran@964
|
437 difference between applied and tracked patches.
|
belaran@964
|
438 </para>
|
belaran@964
|
439
|
belaran@964
|
440 <informalfigure>
|
belaran@964
|
441
|
belaran@964
|
442 <para> <mediaobject><imageobject><imagedata fileref="mq-stack"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject>
|
belaran@964
|
443 <caption><para>Applied and unapplied patches in the MQ patch stack</para></caption>
|
belaran@964
|
444 \label{fig:mq:stack}
|
belaran@964
|
445 </para>
|
belaran@964
|
446 </informalfigure>
|
belaran@964
|
447
|
belaran@964
|
448 <para>You can reapply an unapplied, or popped, patch using the <command role="hg-ext-mq">qpush</command>
|
belaran@964
|
449 command. This creates a new changeset to correspond to the patch, and
|
belaran@964
|
450 the patch's changes once again become present in the working
|
belaran@964
|
451 directory. See figure <xref linkend="ex:mq:qpop"/> for examples of <command role="hg-ext-mq">qpop</command>
|
belaran@964
|
452 and <command role="hg-ext-mq">qpush</command> in action. Notice that once we have popped a patch
|
belaran@964
|
453 or two patches, the output of <command role="hg-ext-mq">qseries</command> remains the same, while
|
belaran@964
|
454 that of <command role="hg-ext-mq">qapplied</command> has changed.
|
belaran@964
|
455 </para>
|
belaran@964
|
456
|
belaran@964
|
457 <informalfigure>
|
belaran@964
|
458 <para> <!-- &interaction.mq.tutorial.qpop; -->
|
belaran@964
|
459 <caption><para>Modifying the stack of applied patches</para></caption>
|
belaran@964
|
460 \label{ex:mq:qpop}
|
belaran@964
|
461 </para>
|
belaran@964
|
462 </informalfigure>
|
belaran@964
|
463
|
belaran@964
|
464 </sect2>
|
belaran@964
|
465 <sect2>
|
belaran@964
|
466 <title>Pushing and popping many patches</title>
|
belaran@964
|
467
|
belaran@964
|
468 <para>While <command role="hg-ext-mq">qpush</command> and <command role="hg-ext-mq">qpop</command> each operate on a single patch at
|
belaran@964
|
469 a time by default, you can push and pop many patches in one go. The
|
belaran@964
|
470 <option role="hg-ext-mq-cmd-qpush-opt">-a</option> option to <command role="hg-ext-mq">qpush</command> causes it to push all
|
belaran@964
|
471 unapplied patches, while the <option role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command role="hg-ext-mq">qpop</command>
|
belaran@964
|
472 causes it to pop all applied patches. (For some more ways to push and
|
belaran@964
|
473 pop many patches, see section <xref linkend="sec:mq:perf"/> below.)
|
belaran@964
|
474 </para>
|
belaran@964
|
475
|
belaran@964
|
476 <informalfigure>
|
belaran@964
|
477 <para> <!-- &interaction.mq.tutorial.qpush-a; -->
|
belaran@964
|
478 <caption><para>Pushing all unapplied patches</para></caption>
|
belaran@964
|
479 \label{ex:mq:qpush-a}
|
belaran@964
|
480 </para>
|
belaran@964
|
481 </informalfigure>
|
belaran@964
|
482
|
belaran@964
|
483 </sect2>
|
belaran@964
|
484 <sect2>
|
belaran@964
|
485 <title>Safety checks, and overriding them</title>
|
belaran@964
|
486
|
belaran@964
|
487 <para>Several MQ commands check the working directory before they do
|
belaran@964
|
488 anything, and fail if they find any modifications. They do this to
|
belaran@964
|
489 ensure that you won't lose any changes that you have made, but not yet
|
belaran@964
|
490 incorporated into a patch. Figure <xref linkend="ex:mq:add"/> illustrates this;
|
belaran@964
|
491 the <command role="hg-ext-mq">qnew</command> command will not create a new patch if there are
|
belaran@964
|
492 outstanding changes, caused in this case by the <command role="hg-cmd">hg add</command> of
|
belaran@964
|
493 <filename>file3</filename>.
|
belaran@964
|
494 </para>
|
belaran@964
|
495
|
belaran@964
|
496 <informalfigure>
|
belaran@964
|
497 <para> <!-- &interaction.mq.tutorial.add; -->
|
belaran@964
|
498 <caption><para>Forcibly creating a patch</para></caption>
|
belaran@964
|
499 \label{ex:mq:add}
|
belaran@964
|
500 </para>
|
belaran@964
|
501 </informalfigure>
|
belaran@964
|
502
|
belaran@964
|
503 <para>Commands that check the working directory all take an <quote>I know what
|
belaran@964
|
504 I'm doing</quote> option, which is always named <option>-f</option>. The exact
|
belaran@964
|
505 meaning of <option>-f</option> depends on the command. For example,
|
belaran@964
|
506 <command role="hg-cmd">hg qnew <option role="hg-ext-mq-cmd-qnew-opt">-f</option></command> will incorporate any outstanding
|
belaran@964
|
507 changes into the new patch it creates, but
|
belaran@964
|
508 <command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-f</option></command> will revert modifications to any
|
belaran@964
|
509 files affected by the patch that it is popping. Be sure to read the
|
belaran@964
|
510 documentation for a command's <option>-f</option> option before you use it!
|
belaran@964
|
511 </para>
|
belaran@964
|
512
|
belaran@964
|
513 </sect2>
|
belaran@964
|
514 <sect2>
|
belaran@964
|
515 <title>Working on several patches at once</title>
|
belaran@964
|
516
|
belaran@964
|
517 <para>The <command role="hg-ext-mq">qrefresh</command> command always refreshes the <emphasis>topmost</emphasis>
|
belaran@964
|
518 applied patch. This means that you can suspend work on one patch (by
|
belaran@964
|
519 refreshing it), pop or push to make a different patch the top, and
|
belaran@964
|
520 work on <emphasis>that</emphasis> patch for a while.
|
belaran@964
|
521 </para>
|
belaran@964
|
522
|
belaran@964
|
523 <para>Here's an example that illustrates how you can use this ability.
|
belaran@964
|
524 Let's say you're developing a new feature as two patches. The first
|
belaran@964
|
525 is a change to the core of your software, and the second&emdash;layered on
|
belaran@964
|
526 top of the first&emdash;changes the user interface to use the code you just
|
belaran@964
|
527 added to the core. If you notice a bug in the core while you're
|
belaran@964
|
528 working on the UI patch, it's easy to fix the core. Simply
|
belaran@964
|
529 <command role="hg-ext-mq">qrefresh</command> the UI patch to save your in-progress changes, and
|
belaran@964
|
530 <command role="hg-ext-mq">qpop</command> down to the core patch. Fix the core bug,
|
belaran@964
|
531 <command role="hg-ext-mq">qrefresh</command> the core patch, and <command role="hg-ext-mq">qpush</command> back to the UI
|
belaran@964
|
532 patch to continue where you left off.
|
belaran@964
|
533 </para>
|
belaran@964
|
534
|
belaran@964
|
535 </sect2>
|
belaran@964
|
536 </sect1>
|
belaran@964
|
537 <sect1>
|
belaran@964
|
538 <title>More about patches</title>
|
belaran@964
|
539 <para>\label{sec:mq:adv-patch}
|
belaran@964
|
540 </para>
|
belaran@964
|
541
|
belaran@964
|
542 <para>MQ uses the GNU <command>patch</command> command to apply patches, so it's
|
belaran@964
|
543 helpful to know a few more detailed aspects of how <command>patch</command>
|
belaran@964
|
544 works, and about patches themselves.
|
belaran@964
|
545 </para>
|
belaran@964
|
546
|
belaran@964
|
547 <sect2>
|
belaran@964
|
548 <title>The strip count</title>
|
belaran@964
|
549
|
belaran@964
|
550 <para>If you look at the file headers in a patch, you will notice that the
|
belaran@964
|
551 pathnames usually have an extra component on the front that isn't
|
belaran@964
|
552 present in the actual path name. This is a holdover from the way that
|
belaran@964
|
553 people used to generate patches (people still do this, but it's
|
belaran@964
|
554 somewhat rare with modern revision control tools).
|
belaran@964
|
555 </para>
|
belaran@964
|
556
|
belaran@964
|
557 <para>Alice would unpack a tarball, edit her files, then decide that she
|
belaran@964
|
558 wanted to create a patch. So she'd rename her working directory,
|
belaran@964
|
559 unpack the tarball again (hence the need for the rename), and use the
|
belaran@964
|
560 <option role="cmd-opt-diff">-r</option> and <option role="cmd-opt-diff">-N</option> options to <command>diff</command> to
|
belaran@964
|
561 recursively generate a patch between the unmodified directory and the
|
belaran@964
|
562 modified one. The result would be that the name of the unmodified
|
belaran@964
|
563 directory would be at the front of the left-hand path in every file
|
belaran@964
|
564 header, and the name of the modified directory would be at the front
|
belaran@964
|
565 of the right-hand path.
|
belaran@964
|
566 </para>
|
belaran@964
|
567
|
belaran@964
|
568 <para>Since someone receiving a patch from the Alices of the net would be
|
belaran@964
|
569 unlikely to have unmodified and modified directories with exactly the
|
belaran@964
|
570 same names, the <command>patch</command> command has a <option role="cmd-opt-patch">-p</option>
|
belaran@964
|
571 option that indicates the number of leading path name components to
|
belaran@964
|
572 strip when trying to apply a patch. This number is called the
|
belaran@964
|
573 <emphasis>strip count</emphasis>.
|
belaran@964
|
574 </para>
|
belaran@964
|
575
|
belaran@964
|
576 <para>An option of <quote><literal>-p1</literal></quote> means <quote>use a strip count of one</quote>. If
|
belaran@964
|
577 <command>patch</command> sees a file name <filename>foo/bar/baz</filename> in a file
|
belaran@964
|
578 header, it will strip <filename>foo</filename> and try to patch a file named
|
belaran@964
|
579 <filename>bar/baz</filename>. (Strictly speaking, the strip count refers to the
|
belaran@964
|
580 number of <emphasis>path separators</emphasis> (and the components that go with them
|
belaran@964
|
581 ) to strip. A strip count of one will turn <filename>foo/bar</filename> into
|
belaran@964
|
582 <filename>bar</filename>, but <filename>/foo/bar</filename> (notice the extra leading
|
belaran@964
|
583 slash) into <filename>foo/bar</filename>.)
|
belaran@964
|
584 </para>
|
belaran@964
|
585
|
belaran@964
|
586 <para>The <quote>standard</quote> strip count for patches is one; almost all patches
|
belaran@964
|
587 contain one leading path name component that needs to be stripped.
|
belaran@964
|
588 Mercurial's <command role="hg-cmd">hg diff</command> command generates path names in this form,
|
belaran@964
|
589 and the <command role="hg-cmd">hg import</command> command and MQ expect patches to have a strip
|
belaran@964
|
590 count of one.
|
belaran@964
|
591 </para>
|
belaran@964
|
592
|
belaran@964
|
593 <para>If you receive a patch from someone that you want to add to your patch
|
belaran@964
|
594 queue, and the patch needs a strip count other than one, you cannot
|
belaran@964
|
595 just <command role="hg-ext-mq">qimport</command> the patch, because <command role="hg-ext-mq">qimport</command> does not yet
|
belaran@964
|
596 have a <literal>-p</literal> option (see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue 311</ulink>). Your best bet is to
|
belaran@964
|
597 <command role="hg-ext-mq">qnew</command> a patch of your own, then use <command>patch -p<emphasis>N</emphasis></command>
|
belaran@964
|
598 to apply their patch, followed by <command role="hg-cmd">hg addremove</command> to pick up any
|
belaran@964
|
599 files added or removed by the patch, followed by <command role="hg-ext-mq">qrefresh</command>.
|
belaran@964
|
600 This complexity may become unnecessary; see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue 311</ulink> for details.
|
belaran@964
|
601 </sect2>
|
belaran@964
|
602 <sect2>
|
belaran@964
|
603 <title>Strategies for applying a patch</title>
|
belaran@964
|
604 </para>
|
belaran@964
|
605
|
belaran@964
|
606 <para>When <command>patch</command> applies a hunk, it tries a handful of
|
belaran@964
|
607 successively less accurate strategies to try to make the hunk apply.
|
belaran@964
|
608 This falling-back technique often makes it possible to take a patch
|
belaran@964
|
609 that was generated against an old version of a file, and apply it
|
belaran@964
|
610 against a newer version of that file.
|
belaran@964
|
611 </para>
|
belaran@964
|
612
|
belaran@964
|
613 <para>First, <command>patch</command> tries an exact match, where the line numbers,
|
belaran@964
|
614 the context, and the text to be modified must apply exactly. If it
|
belaran@964
|
615 cannot make an exact match, it tries to find an exact match for the
|
belaran@964
|
616 context, without honouring the line numbering information. If this
|
belaran@964
|
617 succeeds, it prints a line of output saying that the hunk was applied,
|
belaran@964
|
618 but at some <emphasis>offset</emphasis> from the original line number.
|
belaran@964
|
619 </para>
|
belaran@964
|
620
|
belaran@964
|
621 <para>If a context-only match fails, <command>patch</command> removes the first and
|
belaran@964
|
622 last lines of the context, and tries a <emphasis>reduced</emphasis> context-only
|
belaran@964
|
623 match. If the hunk with reduced context succeeds, it prints a message
|
belaran@964
|
624 saying that it applied the hunk with a <emphasis>fuzz factor</emphasis> (the number
|
belaran@964
|
625 after the fuzz factor indicates how many lines of context
|
belaran@964
|
626 <command>patch</command> had to trim before the patch applied).
|
belaran@964
|
627 </para>
|
belaran@964
|
628
|
belaran@964
|
629 <para>When neither of these techniques works, <command>patch</command> prints a
|
belaran@964
|
630 message saying that the hunk in question was rejected. It saves
|
belaran@964
|
631 rejected hunks (also simply called <quote>rejects</quote>) to a file with the
|
belaran@964
|
632 same name, and an added <filename role="special">.rej</filename> extension. It also saves an
|
belaran@964
|
633 unmodified copy of the file with a <filename role="special">.orig</filename> extension; the
|
belaran@964
|
634 copy of the file without any extensions will contain any changes made
|
belaran@964
|
635 by hunks that <emphasis>did</emphasis> apply cleanly. If you have a patch that
|
belaran@964
|
636 modifies <filename>foo</filename> with six hunks, and one of them fails to
|
belaran@964
|
637 apply, you will have: an unmodified <filename>foo.orig</filename>, a
|
belaran@964
|
638 <filename>foo.rej</filename> containing one hunk, and <filename>foo</filename>, containing
|
belaran@964
|
639 the changes made by the five successful hunks.
|
belaran@964
|
640 </para>
|
belaran@964
|
641
|
belaran@964
|
642 </sect2>
|
belaran@964
|
643 <sect2>
|
belaran@964
|
644 <title>Some quirks of patch representation</title>
|
belaran@964
|
645
|
belaran@964
|
646 <para>There are a few useful things to know about how <command>patch</command> works
|
belaran@964
|
647 with files.
|
belaran@964
|
648 </para>
|
belaran@964
|
649 <itemizedlist>
|
belaran@964
|
650 <listitem><para>This should already be obvious, but <command>patch</command> cannot
|
belaran@964
|
651 handle binary files.
|
belaran@964
|
652 </para>
|
belaran@964
|
653 </listitem>
|
belaran@964
|
654 <listitem><para>Neither does it care about the executable bit; it creates new
|
belaran@964
|
655 files as readable, but not executable.
|
belaran@964
|
656 </para>
|
belaran@964
|
657 </listitem>
|
belaran@964
|
658 <listitem><para><command>patch</command> treats the removal of a file as a diff between
|
belaran@964
|
659 the file to be removed and the empty file. So your idea of <quote>I
|
belaran@964
|
660 deleted this file</quote> looks like <quote>every line of this file was
|
belaran@964
|
661 deleted</quote> in a patch.
|
belaran@964
|
662 </para>
|
belaran@964
|
663 </listitem>
|
belaran@964
|
664 <listitem><para>It treats the addition of a file as a diff between the empty
|
belaran@964
|
665 file and the file to be added. So in a patch, your idea of <quote>I
|
belaran@964
|
666 added this file</quote> looks like <quote>every line of this file was added</quote>.
|
belaran@964
|
667 </para>
|
belaran@964
|
668 </listitem>
|
belaran@964
|
669 <listitem><para>It treats a renamed file as the removal of the old name, and the
|
belaran@964
|
670 addition of the new name. This means that renamed files have a big
|
belaran@964
|
671 footprint in patches. (Note also that Mercurial does not currently
|
belaran@964
|
672 try to infer when files have been renamed or copied in a patch.)
|
belaran@964
|
673 </para>
|
belaran@964
|
674 </listitem>
|
belaran@964
|
675 <listitem><para><command>patch</command> cannot represent empty files, so you cannot use
|
belaran@964
|
676 a patch to represent the notion <quote>I added this empty file to the
|
belaran@964
|
677 tree</quote>.
|
belaran@964
|
678 </para>
|
belaran@964
|
679 </listitem></itemizedlist>
|
belaran@964
|
680 </sect2>
|
belaran@964
|
681 <sect2>
|
belaran@964
|
682 <title>Beware the fuzz</title>
|
belaran@964
|
683
|
belaran@964
|
684 <para>While applying a hunk at an offset, or with a fuzz factor, will often
|
belaran@964
|
685 be completely successful, these inexact techniques naturally leave
|
belaran@964
|
686 open the possibility of corrupting the patched file. The most common
|
belaran@964
|
687 cases typically involve applying a patch twice, or at an incorrect
|
belaran@964
|
688 location in the file. If <command>patch</command> or <command role="hg-ext-mq">qpush</command> ever
|
belaran@964
|
689 mentions an offset or fuzz factor, you should make sure that the
|
belaran@964
|
690 modified files are correct afterwards.
|
belaran@964
|
691 </para>
|
belaran@964
|
692
|
belaran@964
|
693 <para>It's often a good idea to refresh a patch that has applied with an
|
belaran@964
|
694 offset or fuzz factor; refreshing the patch generates new context
|
belaran@964
|
695 information that will make it apply cleanly. I say <quote>often,</quote> not
|
belaran@964
|
696 <quote>always,</quote> because sometimes refreshing a patch will make it fail to
|
belaran@964
|
697 apply against a different revision of the underlying files. In some
|
belaran@964
|
698 cases, such as when you're maintaining a patch that must sit on top of
|
belaran@964
|
699 multiple versions of a source tree, it's acceptable to have a patch
|
belaran@964
|
700 apply with some fuzz, provided you've verified the results of the
|
belaran@964
|
701 patching process in such cases.
|
belaran@964
|
702 </para>
|
belaran@964
|
703
|
belaran@964
|
704 </sect2>
|
belaran@964
|
705 <sect2>
|
belaran@964
|
706 <title>Handling rejection</title>
|
belaran@964
|
707
|
belaran@964
|
708 <para>If <command role="hg-ext-mq">qpush</command> fails to apply a patch, it will print an error
|
belaran@964
|
709 message and exit. If it has left <filename role="special">.rej</filename> files behind, it is
|
belaran@964
|
710 usually best to fix up the rejected hunks before you push more patches
|
belaran@964
|
711 or do any further work.
|
belaran@964
|
712 </para>
|
belaran@964
|
713
|
belaran@964
|
714 <para>If your patch <emphasis>used to</emphasis> apply cleanly, and no longer does because
|
belaran@964
|
715 you've changed the underlying code that your patches are based on,
|
belaran@964
|
716 Mercurial Queues can help; see section <xref linkend="sec:mq:merge"/> for details.
|
belaran@964
|
717 </para>
|
belaran@964
|
718
|
belaran@964
|
719 <para>Unfortunately, there aren't any great techniques for dealing with
|
belaran@964
|
720 rejected hunks. Most often, you'll need to view the <filename role="special">.rej</filename>
|
belaran@964
|
721 file and edit the target file, applying the rejected hunks by hand.
|
belaran@964
|
722 </para>
|
belaran@964
|
723
|
belaran@964
|
724 <para>If you're feeling adventurous, Neil Brown, a Linux kernel hacker,
|
belaran@964
|
725 wrote a tool called <command>wiggle</command> <citation>web:wiggle</citation>, which is more
|
belaran@964
|
726 vigorous than <command>patch</command> in its attempts to make a patch apply.
|
belaran@964
|
727 </para>
|
belaran@964
|
728
|
belaran@964
|
729 <para>Another Linux kernel hacker, Chris Mason (the author of Mercurial
|
belaran@964
|
730 Queues), wrote a similar tool called
|
belaran@964
|
731 <command>mpatch</command> <citation>web:mpatch</citation>, which takes a simple approach to
|
belaran@964
|
732 automating the application of hunks rejected by <command>patch</command>. The
|
belaran@964
|
733 <command>mpatch</command> command can help with four common reasons that a hunk
|
belaran@964
|
734 may be rejected:
|
belaran@964
|
735 </para>
|
belaran@964
|
736
|
belaran@964
|
737 <itemizedlist>
|
belaran@964
|
738 <listitem><para>The context in the middle of a hunk has changed.
|
belaran@964
|
739 </para>
|
belaran@964
|
740 </listitem>
|
belaran@964
|
741 <listitem><para>A hunk is missing some context at the beginning or end.
|
belaran@964
|
742 </para>
|
belaran@964
|
743 </listitem>
|
belaran@964
|
744 <listitem><para>A large hunk might apply better&emdash;either entirely or in
|
belaran@964
|
745 part&emdash;if it was broken up into smaller hunks.
|
belaran@964
|
746 </para>
|
belaran@964
|
747 </listitem>
|
belaran@964
|
748 <listitem><para>A hunk removes lines with slightly different content than those
|
belaran@964
|
749 currently present in the file.
|
belaran@964
|
750 </para>
|
belaran@964
|
751 </listitem></itemizedlist>
|
belaran@964
|
752
|
belaran@964
|
753 <para>If you use <command>wiggle</command> or <command>mpatch</command>, you should be doubly
|
belaran@964
|
754 careful to check your results when you're done. In fact,
|
belaran@964
|
755 <command>mpatch</command> enforces this method of double-checking the tool's
|
belaran@964
|
756 output, by automatically dropping you into a merge program when it has
|
belaran@964
|
757 done its job, so that you can verify its work and finish off any
|
belaran@964
|
758 remaining merges.
|
belaran@964
|
759 </para>
|
belaran@964
|
760
|
belaran@964
|
761 </sect2>
|
belaran@964
|
762 </sect1>
|
belaran@964
|
763 <sect1>
|
belaran@964
|
764 <title>Getting the best performance out of MQ</title>
|
belaran@964
|
765 <para>\label{sec:mq:perf}
|
belaran@964
|
766 </para>
|
belaran@964
|
767
|
belaran@964
|
768 <para>MQ is very efficient at handling a large number of patches. I ran
|
belaran@964
|
769 some performance experiments in mid-2006 for a talk that I gave at the
|
belaran@964
|
770 2006 EuroPython conference <citation>web:europython</citation>. I used as my data
|
belaran@964
|
771 set the Linux 2.6.17-mm1 patch series, which consists of 1,738
|
belaran@964
|
772 patches. I applied these on top of a Linux kernel repository
|
belaran@964
|
773 containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux
|
belaran@964
|
774 2.6.17.
|
belaran@964
|
775 </para>
|
belaran@964
|
776
|
belaran@964
|
777 <para>On my old, slow laptop, I was able to
|
belaran@964
|
778 <command role="hg-cmd">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">-a</option></command> all 1,738 patches in 3.5 minutes,
|
belaran@964
|
779 and <command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command> them all in 30 seconds. (On a
|
belaran@964
|
780 newer laptop, the time to push all patches dropped to two minutes.) I
|
belaran@964
|
781 could <command role="hg-ext-mq">qrefresh</command> one of the biggest patches (which made 22,779
|
belaran@964
|
782 lines of changes to 287 files) in 6.6 seconds.
|
belaran@964
|
783 </para>
|
belaran@964
|
784
|
belaran@964
|
785 <para>Clearly, MQ is well suited to working in large trees, but there are a
|
belaran@964
|
786 few tricks you can use to get the best performance of it.
|
belaran@964
|
787 </para>
|
belaran@964
|
788
|
belaran@964
|
789 <para>First of all, try to <quote>batch</quote> operations together. Every time you
|
belaran@964
|
790 run <command role="hg-ext-mq">qpush</command> or <command role="hg-ext-mq">qpop</command>, these commands scan the working
|
belaran@964
|
791 directory once to make sure you haven't made some changes and then
|
belaran@964
|
792 forgotten to run <command role="hg-ext-mq">qrefresh</command>. On a small tree, the time that
|
belaran@964
|
793 this scan takes is unnoticeable. However, on a medium-sized tree
|
belaran@964
|
794 (containing tens of thousands of files), it can take a second or more.
|
belaran@964
|
795 </para>
|
belaran@964
|
796
|
belaran@964
|
797 <para>The <command role="hg-ext-mq">qpush</command> and <command role="hg-ext-mq">qpop</command> commands allow you to push and pop
|
belaran@964
|
798 multiple patches at a time. You can identify the <quote>destination
|
belaran@964
|
799 patch</quote> that you want to end up at. When you <command role="hg-ext-mq">qpush</command> with a
|
belaran@964
|
800 destination specified, it will push patches until that patch is at the
|
belaran@964
|
801 top of the applied stack. When you <command role="hg-ext-mq">qpop</command> to a destination, MQ
|
belaran@964
|
802 will pop patches until the destination patch is at the top.
|
belaran@964
|
803 </para>
|
belaran@964
|
804
|
belaran@964
|
805 <para>You can identify a destination patch using either the name of the
|
belaran@964
|
806 patch, or by number. If you use numeric addressing, patches are
|
belaran@964
|
807 counted from zero; this means that the first patch is zero, the second
|
belaran@964
|
808 is one, and so on.
|
belaran@964
|
809 </para>
|
belaran@964
|
810
|
belaran@964
|
811 </sect1>
|
belaran@964
|
812 <sect1>
|
belaran@964
|
813 <title>Updating your patches when the underlying code changes</title>
|
belaran@964
|
814 <para>\label{sec:mq:merge}
|
belaran@964
|
815 </para>
|
belaran@964
|
816
|
belaran@964
|
817 <para>It's common to have a stack of patches on top of an underlying
|
belaran@964
|
818 repository that you don't modify directly. If you're working on
|
belaran@964
|
819 changes to third-party code, or on a feature that is taking longer to
|
belaran@964
|
820 develop than the rate of change of the code beneath, you will often
|
belaran@964
|
821 need to sync up with the underlying code, and fix up any hunks in your
|
belaran@964
|
822 patches that no longer apply. This is called <emphasis>rebasing</emphasis> your
|
belaran@964
|
823 patch series.
|
belaran@964
|
824 </para>
|
belaran@964
|
825
|
belaran@964
|
826 <para>The simplest way to do this is to <command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command>
|
belaran@964
|
827 your patches, then <command role="hg-cmd">hg pull</command> changes into the underlying
|
belaran@964
|
828 repository, and finally <command role="hg-cmd">hg qpush <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command> your
|
belaran@964
|
829 patches again. MQ will stop pushing any time it runs across a patch
|
belaran@964
|
830 that fails to apply during conflicts, allowing you to fix your
|
belaran@964
|
831 conflicts, <command role="hg-ext-mq">qrefresh</command> the affected patch, and continue pushing
|
belaran@964
|
832 until you have fixed your entire stack.
|
belaran@964
|
833 </para>
|
belaran@964
|
834
|
belaran@964
|
835 <para>This approach is easy to use and works well if you don't expect
|
belaran@964
|
836 changes to the underlying code to affect how well your patches apply.
|
belaran@964
|
837 If your patch stack touches code that is modified frequently or
|
belaran@964
|
838 invasively in the underlying repository, however, fixing up rejected
|
belaran@964
|
839 hunks by hand quickly becomes tiresome.
|
belaran@964
|
840 </para>
|
belaran@964
|
841
|
belaran@964
|
842 <para>It's possible to partially automate the rebasing process. If your
|
belaran@964
|
843 patches apply cleanly against some revision of the underlying repo, MQ
|
belaran@964
|
844 can use this information to help you to resolve conflicts between your
|
belaran@964
|
845 patches and a different revision.
|
belaran@964
|
846 </para>
|
belaran@964
|
847
|
belaran@964
|
848 <para>The process is a little involved.
|
belaran@964
|
849 </para>
|
belaran@964
|
850 <orderedlist>
|
belaran@964
|
851 <listitem><para>To begin, <command role="hg-cmd">hg qpush -a</command> all of your patches on top of
|
belaran@964
|
852 the revision where you know that they apply cleanly.
|
belaran@964
|
853 </para>
|
belaran@964
|
854 </listitem>
|
belaran@964
|
855 <listitem><para>Save a backup copy of your patch directory using
|
belaran@964
|
856 <command role="hg-cmd">hg qsave <option role="hg-ext-mq-cmd-qsave-opt">-e</option> <option role="hg-ext-mq-cmd-qsave-opt">-c</option></command>. This prints
|
belaran@964
|
857 the name of the directory that it has saved the patches in. It will
|
belaran@964
|
858 save the patches to a directory called
|
belaran@964
|
859 <filename role="special" class="directory">.hg/patches.<emphasis>N</filename></emphasis>, where <literal><emphasis>N</emphasis></literal> is a small
|
belaran@964
|
860 integer. It also commits a <quote>save changeset</quote> on top of your
|
belaran@964
|
861 applied patches; this is for internal book-keeping, and records the
|
belaran@964
|
862 states of the <filename role="special">series</filename> and <filename role="special">status</filename> files.
|
belaran@964
|
863 </para>
|
belaran@964
|
864 </listitem>
|
belaran@964
|
865 <listitem><para>Use <command role="hg-cmd">hg pull</command> to bring new changes into the underlying
|
belaran@964
|
866 repository. (Don't run <command role="hg-cmd">hg pull -u</command>; see below for why.)
|
belaran@964
|
867 </para>
|
belaran@964
|
868 </listitem>
|
belaran@964
|
869 <listitem><para>Update to the new tip revision, using
|
belaran@964
|
870 <command role="hg-cmd">hg update <option role="hg-opt-update">-C</option></command> to override the patches you
|
belaran@964
|
871 have pushed.
|
belaran@964
|
872 </para>
|
belaran@964
|
873 </listitem>
|
belaran@964
|
874 <listitem><para>Merge all patches using \hgcmdargs{qpush}{<option role="hg-ext-mq-cmd-qpush-opt">-m</option>
|
belaran@964
|
875 <option role="hg-ext-mq-cmd-qpush-opt">-a</option>}. The <option role="hg-ext-mq-cmd-qpush-opt">-m</option> option to <command role="hg-ext-mq">qpush</command>
|
belaran@964
|
876 tells MQ to perform a three-way merge if the patch fails to apply.
|
belaran@964
|
877 </para>
|
belaran@964
|
878 </listitem></orderedlist>
|
belaran@964
|
879
|
belaran@964
|
880 <para>During the <command role="hg-cmd">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">-m</option></command>, each patch in the
|
belaran@964
|
881 <filename role="special">series</filename> file is applied normally. If a patch applies with
|
belaran@964
|
882 fuzz or rejects, MQ looks at the queue you <command role="hg-ext-mq">qsave</command>d, and
|
belaran@964
|
883 performs a three-way merge with the corresponding changeset. This
|
belaran@964
|
884 merge uses Mercurial's normal merge machinery, so it may pop up a GUI
|
belaran@964
|
885 merge tool to help you to resolve problems.
|
belaran@964
|
886 </para>
|
belaran@964
|
887
|
belaran@964
|
888 <para>When you finish resolving the effects of a patch, MQ refreshes your
|
belaran@964
|
889 patch based on the result of the merge.
|
belaran@964
|
890 </para>
|
belaran@964
|
891
|
belaran@964
|
892 <para>At the end of this process, your repository will have one extra head
|
belaran@964
|
893 from the old patch queue, and a copy of the old patch queue will be in
|
belaran@964
|
894 <filename role="special" class="directory">.hg/patches.<emphasis>N</filename></emphasis>. You can remove the extra head using
|
belaran@964
|
895 <command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-a</option> <option role="hg-ext-mq-cmd-qpop-opt">-n</option> patches.<emphasis>N</emphasis></command>
|
belaran@964
|
896 or <command role="hg-cmd">hg strip</command>. You can delete <filename role="special" class="directory">.hg/patches.<emphasis>N</filename></emphasis> once
|
belaran@964
|
897 you are sure that you no longer need it as a backup.
|
belaran@964
|
898 </para>
|
belaran@964
|
899
|
belaran@964
|
900 </sect1>
|
belaran@964
|
901 <sect1>
|
belaran@964
|
902 <title>Identifying patches</title>
|
belaran@964
|
903
|
belaran@964
|
904 <para>MQ commands that work with patches let you refer to a patch either by
|
belaran@964
|
905 using its name or by a number. By name is obvious enough; pass the
|
belaran@964
|
906 name <filename>foo.patch</filename> to <command role="hg-ext-mq">qpush</command>, for example, and it will
|
belaran@964
|
907 push patches until <filename>foo.patch</filename> is applied.
|
belaran@964
|
908 </para>
|
belaran@964
|
909
|
belaran@964
|
910 <para>As a shortcut, you can refer to a patch using both a name and a
|
belaran@964
|
911 numeric offset; <literal>foo.patch-2</literal> means <quote>two patches before
|
belaran@964
|
912 <literal>foo.patch</literal></quote>, while <literal>bar.patch+4</literal> means <quote>four patches
|
belaran@964
|
913 after <literal>bar.patch</literal></quote>.
|
belaran@964
|
914 </para>
|
belaran@964
|
915
|
belaran@964
|
916 <para>Referring to a patch by index isn't much different. The first patch
|
belaran@964
|
917 printed in the output of <command role="hg-ext-mq">qseries</command> is patch zero (yes, it's one
|
belaran@964
|
918 of those start-at-zero counting systems); the second is patch one; and
|
belaran@964
|
919 so on.
|
belaran@964
|
920 </para>
|
belaran@964
|
921
|
belaran@964
|
922 <para>MQ also makes it easy to work with patches when you are using normal
|
belaran@964
|
923 Mercurial commands. Every command that accepts a changeset ID will
|
belaran@964
|
924 also accept the name of an applied patch. MQ augments the tags
|
belaran@964
|
925 normally in the repository with an eponymous one for each applied
|
belaran@964
|
926 patch. In addition, the special tags \index{tags!special tag
|
belaran@964
|
927 names!<literal>qbase</literal>}<literal>qbase</literal> and \index{tags!special tag
|
belaran@964
|
928 names!<literal>qtip</literal>}<literal>qtip</literal> identify the <quote>bottom-most</quote> and
|
belaran@964
|
929 topmost applied patches, respectively.
|
belaran@964
|
930 </para>
|
belaran@964
|
931
|
belaran@964
|
932 <para>These additions to Mercurial's normal tagging capabilities make
|
belaran@964
|
933 dealing with patches even more of a breeze.
|
belaran@964
|
934 </para>
|
belaran@964
|
935 <itemizedlist>
|
belaran@964
|
936 <listitem><para>Want to patchbomb a mailing list with your latest series of
|
belaran@964
|
937 changes?
|
belaran@964
|
938 </para>
|
belaran@964
|
939 </listitem><programlisting>
|
belaran@964
|
940 <listitem><para> hg email qbase:qtip
|
belaran@964
|
941 </para>
|
belaran@964
|
942 </listitem></programlisting>
|
belaran@964
|
943 <listitem><para> (Don't know what <quote>patchbombing</quote> is? See
|
belaran@964
|
944 section <xref linkend="sec:hgext:patchbomb"/>.)
|
belaran@964
|
945 </para>
|
belaran@964
|
946 </listitem>
|
belaran@964
|
947 <listitem><para>Need to see all of the patches since <literal>foo.patch</literal> that
|
belaran@964
|
948 have touched files in a subdirectory of your tree?
|
belaran@964
|
949 </para>
|
belaran@964
|
950 </listitem><programlisting>
|
belaran@964
|
951 <listitem><para> hg log -r foo.patch:qtip <emphasis>subdir</emphasis>
|
belaran@964
|
952 </para>
|
belaran@964
|
953 </listitem></programlisting>
|
belaran@964
|
954 </itemizedlist>
|
belaran@964
|
955
|
belaran@964
|
956 <para>Because MQ makes the names of patches available to the rest of
|
belaran@964
|
957 Mercurial through its normal internal tag machinery, you don't need to
|
belaran@964
|
958 type in the entire name of a patch when you want to identify it by
|
belaran@964
|
959 name.
|
belaran@964
|
960 </para>
|
belaran@964
|
961
|
belaran@964
|
962 <informalfigure>
|
belaran@964
|
963 <para> <!-- &interaction.mq.id.output; -->
|
belaran@964
|
964 <caption><para>Using MQ's tag features to work with patches</para></caption>
|
belaran@964
|
965 \label{ex:mq:id}
|
belaran@964
|
966 </para>
|
belaran@964
|
967 </informalfigure>
|
belaran@964
|
968
|
belaran@964
|
969 <para>Another nice consequence of representing patch names as tags is that
|
belaran@964
|
970 when you run the <command role="hg-cmd">hg log</command> command, it will display a patch's name
|
belaran@964
|
971 as a tag, simply as part of its normal output. This makes it easy to
|
belaran@964
|
972 visually distinguish applied patches from underlying <quote>normal</quote>
|
belaran@964
|
973 revisions. Figure <xref linkend="ex:mq:id"/> shows a few normal Mercurial
|
belaran@964
|
974 commands in use with applied patches.
|
belaran@964
|
975 </para>
|
belaran@964
|
976
|
belaran@964
|
977 </sect1>
|
belaran@964
|
978 <sect1>
|
belaran@964
|
979 <title>Useful things to know about</title>
|
belaran@964
|
980
|
belaran@964
|
981 <para>There are a number of aspects of MQ usage that don't fit tidily into
|
belaran@964
|
982 sections of their own, but that are good to know. Here they are, in
|
belaran@964
|
983 one place.
|
belaran@964
|
984 </para>
|
belaran@964
|
985
|
belaran@964
|
986 <itemizedlist>
|
belaran@964
|
987 <listitem><para>Normally, when you <command role="hg-ext-mq">qpop</command> a patch and <command role="hg-ext-mq">qpush</command> it
|
belaran@964
|
988 again, the changeset that represents the patch after the pop/push
|
belaran@964
|
989 will have a <emphasis>different identity</emphasis> than the changeset that
|
belaran@964
|
990 represented the hash beforehand. See
|
belaran@964
|
991 section <xref linkend="sec:mqref:cmd:qpush"/> for information as to why this is.
|
belaran@964
|
992 </para>
|
belaran@964
|
993 </listitem>
|
belaran@964
|
994 <listitem><para>It's not a good idea to <command role="hg-cmd">hg merge</command> changes from another
|
belaran@964
|
995 branch with a patch changeset, at least if you want to maintain the
|
belaran@964
|
996 <quote>patchiness</quote> of that changeset and changesets below it on the
|
belaran@964
|
997 patch stack. If you try to do this, it will appear to succeed, but
|
belaran@964
|
998 MQ will become confused.
|
belaran@964
|
999 </para>
|
belaran@964
|
1000 </listitem></itemizedlist>
|
belaran@964
|
1001
|
belaran@964
|
1002 </sect1>
|
belaran@964
|
1003 <sect1>
|
belaran@964
|
1004 <title>Managing patches in a repository</title>
|
belaran@964
|
1005 <para>\label{sec:mq:repo}
|
belaran@964
|
1006 </para>
|
belaran@964
|
1007
|
belaran@964
|
1008 <para>Because MQ's <filename role="special" class="directory">.hg/patches</filename> directory resides outside a
|
belaran@964
|
1009 Mercurial repository's working directory, the <quote>underlying</quote> Mercurial
|
belaran@964
|
1010 repository knows nothing about the management or presence of patches.
|
belaran@964
|
1011 </para>
|
belaran@964
|
1012
|
belaran@964
|
1013 <para>This presents the interesting possibility of managing the contents of
|
belaran@964
|
1014 the patch directory as a Mercurial repository in its own right. This
|
belaran@964
|
1015 can be a useful way to work. For example, you can work on a patch for
|
belaran@964
|
1016 a while, <command role="hg-ext-mq">qrefresh</command> it, then <command role="hg-cmd">hg commit</command> the current state of
|
belaran@964
|
1017 the patch. This lets you <quote>roll back</quote> to that version of the patch
|
belaran@964
|
1018 later on.
|
belaran@964
|
1019 </para>
|
belaran@964
|
1020
|
belaran@964
|
1021 <para>You can then share different versions of the same patch stack among
|
belaran@964
|
1022 multiple underlying repositories. I use this when I am developing a
|
belaran@964
|
1023 Linux kernel feature. I have a pristine copy of my kernel sources for
|
belaran@964
|
1024 each of several CPU architectures, and a cloned repository under each
|
belaran@964
|
1025 that contains the patches I am working on. When I want to test a
|
belaran@964
|
1026 change on a different architecture, I push my current patches to the
|
belaran@964
|
1027 patch repository associated with that kernel tree, pop and push all of
|
belaran@964
|
1028 my patches, and build and test that kernel.
|
belaran@964
|
1029 </para>
|
belaran@964
|
1030
|
belaran@964
|
1031 <para>Managing patches in a repository makes it possible for multiple
|
belaran@964
|
1032 developers to work on the same patch series without colliding with
|
belaran@964
|
1033 each other, all on top of an underlying source base that they may or
|
belaran@964
|
1034 may not control.
|
belaran@964
|
1035 </para>
|
belaran@964
|
1036
|
belaran@964
|
1037 <sect2>
|
belaran@964
|
1038 <title>MQ support for patch repositories</title>
|
belaran@964
|
1039
|
belaran@964
|
1040 <para>MQ helps you to work with the <filename role="special" class="directory">.hg/patches</filename> directory as a
|
belaran@964
|
1041 repository; when you prepare a repository for working with patches
|
belaran@964
|
1042 using <command role="hg-ext-mq">qinit</command>, you can pass the <option role="hg-ext-mq-cmd-qinit-opt">-c</option> option to
|
belaran@964
|
1043 create the <filename role="special" class="directory">.hg/patches</filename> directory as a Mercurial repository.
|
belaran@964
|
1044 </para>
|
belaran@964
|
1045
|
belaran@964
|
1046 <note>
|
belaran@964
|
1047 <para> If you forget to use the <option role="hg-ext-mq-cmd-qinit-opt">-c</option> option, you can simply go
|
belaran@964
|
1048 into the <filename role="special" class="directory">.hg/patches</filename> directory at any time and run
|
belaran@964
|
1049 <command role="hg-cmd">hg init</command>. Don't forget to add an entry for the
|
belaran@964
|
1050 <filename role="special">status</filename> file to the <filename role="special">.hgignore</filename> file, though
|
belaran@964
|
1051 </para>
|
belaran@964
|
1052
|
belaran@964
|
1053 <para> (<command role="hg-cmd">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">-c</option></command> does this for you
|
belaran@964
|
1054 automatically); you <emphasis>really</emphasis> don't want to manage the
|
belaran@964
|
1055 <filename role="special">status</filename> file.
|
belaran@964
|
1056 </para>
|
belaran@964
|
1057 </note>
|
belaran@964
|
1058
|
belaran@964
|
1059 <para>As a convenience, if MQ notices that the <filename class="directory">.hg/patches</filename>
|
belaran@964
|
1060 directory is a repository, it will automatically <command role="hg-cmd">hg add</command> every
|
belaran@964
|
1061 patch that you create and import.
|
belaran@964
|
1062 </para>
|
belaran@964
|
1063
|
belaran@964
|
1064 <para>MQ provides a shortcut command, <command role="hg-ext-mq">qcommit</command>, that runs
|
belaran@964
|
1065 <command role="hg-cmd">hg commit</command> in the <filename role="special" class="directory">.hg/patches</filename> directory. This saves
|
belaran@964
|
1066 some bothersome typing.
|
belaran@964
|
1067 </para>
|
belaran@964
|
1068
|
belaran@964
|
1069 <para>Finally, as a convenience to manage the patch directory, you can
|
belaran@964
|
1070 define the alias <command>mq</command> on Unix systems. For example, on Linux
|
belaran@964
|
1071 systems using the <command>bash</command> shell, you can include the following
|
belaran@964
|
1072 snippet in your <filename role="home">~/.bashrc</filename>.
|
belaran@964
|
1073 </para>
|
belaran@964
|
1074
|
belaran@964
|
1075 <programlisting>
|
belaran@964
|
1076 <para> alias mq=`hg -R $(hg root)/.hg/patches'
|
belaran@964
|
1077 </para>
|
belaran@964
|
1078 </programlisting>
|
belaran@964
|
1079
|
belaran@964
|
1080 <para>You can then issue commands of the form <command>mq pull</command> from
|
belaran@964
|
1081 the main repository.
|
belaran@964
|
1082 </para>
|
belaran@964
|
1083
|
belaran@964
|
1084 </sect2>
|
belaran@964
|
1085 <sect2>
|
belaran@964
|
1086 <title>A few things to watch out for</title>
|
belaran@964
|
1087
|
belaran@964
|
1088 <para>MQ's support for working with a repository full of patches is limited
|
belaran@964
|
1089 in a few small respects.
|
belaran@964
|
1090 </para>
|
belaran@964
|
1091
|
belaran@964
|
1092 <para>MQ cannot automatically detect changes that you make to the patch
|
belaran@964
|
1093 directory. If you <command role="hg-cmd">hg pull</command>, manually edit, or <command role="hg-cmd">hg update</command>
|
belaran@964
|
1094 changes to patches or the <filename role="special">series</filename> file, you will have to
|
belaran@964
|
1095 <command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command> and then
|
belaran@964
|
1096 <command role="hg-cmd">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">-a</option></command> in the underlying repository to
|
belaran@964
|
1097 see those changes show up there. If you forget to do this, you can
|
belaran@964
|
1098 confuse MQ's idea of which patches are applied.
|
belaran@964
|
1099 </para>
|
belaran@964
|
1100
|
belaran@964
|
1101 </sect2>
|
belaran@964
|
1102 </sect1>
|
belaran@964
|
1103 <sect1>
|
belaran@964
|
1104 <title>Third party tools for working with patches</title>
|
belaran@964
|
1105 <para>\label{sec:mq:tools}
|
belaran@964
|
1106 </para>
|
belaran@964
|
1107
|
belaran@964
|
1108 <para>Once you've been working with patches for a while, you'll find
|
belaran@964
|
1109 yourself hungry for tools that will help you to understand and
|
belaran@964
|
1110 manipulate the patches you're dealing with.
|
belaran@964
|
1111 </para>
|
belaran@964
|
1112
|
belaran@964
|
1113 <para>The <command>diffstat</command> command <citation>web:diffstat</citation> generates a
|
belaran@964
|
1114 histogram of the modifications made to each file in a patch. It
|
belaran@964
|
1115 provides a good way to <quote>get a sense of</quote> a patch&emdash;which files it
|
belaran@964
|
1116 affects, and how much change it introduces to each file and as a
|
belaran@964
|
1117 whole. (I find that it's a good idea to use <command>diffstat</command>'s
|
belaran@964
|
1118 <option role="cmd-opt-diffstat">-p</option> option as a matter of course, as otherwise it
|
belaran@964
|
1119 will try to do clever things with prefixes of file names that
|
belaran@964
|
1120 inevitably confuse at least me.)
|
belaran@964
|
1121 </para>
|
belaran@964
|
1122
|
belaran@964
|
1123 <informalfigure>
|
belaran@964
|
1124 <para> <!-- &interaction.mq.tools.tools; -->
|
belaran@964
|
1125 <caption><para>The <command>diffstat</para></caption>, \command{filterdiff</command>, and <command>lsdiff</command> commands}
|
belaran@964
|
1126 \label{ex:mq:tools}
|
belaran@964
|
1127 </para>
|
belaran@964
|
1128 </informalfigure>
|
belaran@964
|
1129
|
belaran@964
|
1130 <para>The <literal role="package">patchutils</literal> package <citation>web:patchutils</citation> is invaluable.
|
belaran@964
|
1131 It provides a set of small utilities that follow the <quote>Unix
|
belaran@964
|
1132 philosophy;</quote> each does one useful thing with a patch. The
|
belaran@964
|
1133 <literal role="package">patchutils</literal> command I use most is <command>filterdiff</command>, which
|
belaran@964
|
1134 extracts subsets from a patch file. For example, given a patch that
|
belaran@964
|
1135 modifies hundreds of files across dozens of directories, a single
|
belaran@964
|
1136 invocation of <command>filterdiff</command> can generate a smaller patch that
|
belaran@964
|
1137 only touches files whose names match a particular glob pattern. See
|
belaran@964
|
1138 section <xref linkend="mq-collab:tips:interdiff"/> for another example.
|
belaran@964
|
1139 </para>
|
belaran@964
|
1140
|
belaran@964
|
1141 </sect1>
|
belaran@964
|
1142 <sect1>
|
belaran@964
|
1143 <title>Good ways to work with patches</title>
|
belaran@964
|
1144
|
belaran@964
|
1145 <para>Whether you are working on a patch series to submit to a free software
|
belaran@964
|
1146 or open source project, or a series that you intend to treat as a
|
belaran@964
|
1147 sequence of regular changesets when you're done, you can use some
|
belaran@964
|
1148 simple techniques to keep your work well organised.
|
belaran@964
|
1149 </para>
|
belaran@964
|
1150
|
belaran@964
|
1151 <para>Give your patches descriptive names. A good name for a patch might be
|
belaran@964
|
1152 <filename>rework-device-alloc.patch</filename>, because it will immediately give
|
belaran@964
|
1153 you a hint what the purpose of the patch is. Long names shouldn't be
|
belaran@964
|
1154 a problem; you won't be typing the names often, but you <emphasis>will</emphasis> be
|
belaran@964
|
1155 running commands like <command role="hg-ext-mq">qapplied</command> and <command role="hg-ext-mq">qtop</command> over and over.
|
belaran@964
|
1156 Good naming becomes especially important when you have a number of
|
belaran@964
|
1157 patches to work with, or if you are juggling a number of different
|
belaran@964
|
1158 tasks and your patches only get a fraction of your attention.
|
belaran@964
|
1159 </para>
|
belaran@964
|
1160
|
belaran@964
|
1161 <para>Be aware of what patch you're working on. Use the <command role="hg-ext-mq">qtop</command>
|
belaran@964
|
1162 command and skim over the text of your patches frequently&emdash;for
|
belaran@964
|
1163 example, using <command role="hg-cmd">hg tip <option role="hg-opt-tip">-p</option></command>)&emdash;to be sure of where
|
belaran@964
|
1164 you stand. I have several times worked on and <command role="hg-ext-mq">qrefresh</command>ed a
|
belaran@964
|
1165 patch other than the one I intended, and it's often tricky to migrate
|
belaran@964
|
1166 changes into the right patch after making them in the wrong one.
|
belaran@964
|
1167 </para>
|
belaran@964
|
1168
|
belaran@964
|
1169 <para>For this reason, it is very much worth investing a little time to
|
belaran@964
|
1170 learn how to use some of the third-party tools I described in
|
belaran@964
|
1171 section <xref linkend="sec:mq:tools"/>, particularly <command>diffstat</command> and
|
belaran@964
|
1172 <command>filterdiff</command>. The former will give you a quick idea of what
|
belaran@964
|
1173 changes your patch is making, while the latter makes it easy to splice
|
belaran@964
|
1174 hunks selectively out of one patch and into another.
|
belaran@964
|
1175 </para>
|
belaran@964
|
1176
|
belaran@964
|
1177 </sect1>
|
belaran@964
|
1178 <sect1>
|
belaran@964
|
1179 <title>MQ cookbook</title>
|
belaran@964
|
1180
|
belaran@964
|
1181 <sect2>
|
belaran@964
|
1182 <title>Manage <quote>trivial</quote> patches</title>
|
belaran@964
|
1183
|
belaran@964
|
1184 <para>Because the overhead of dropping files into a new Mercurial repository
|
belaran@964
|
1185 is so low, it makes a lot of sense to manage patches this way even if
|
belaran@964
|
1186 you simply want to make a few changes to a source tarball that you
|
belaran@964
|
1187 downloaded.
|
belaran@964
|
1188 </para>
|
belaran@964
|
1189
|
belaran@964
|
1190 <para>Begin by downloading and unpacking the source tarball,
|
belaran@964
|
1191 and turning it into a Mercurial repository.
|
belaran@964
|
1192 <!-- &interaction.mq.tarball.download; -->
|
belaran@964
|
1193 </para>
|
belaran@964
|
1194
|
belaran@964
|
1195 <para>Continue by creating a patch stack and making your changes.
|
belaran@964
|
1196 <!-- &interaction.mq.tarball.qinit; -->
|
belaran@964
|
1197 </para>
|
belaran@964
|
1198
|
belaran@964
|
1199 <para>Let's say a few weeks or months pass, and your package author releases
|
belaran@964
|
1200 a new version. First, bring their changes into the repository.
|
belaran@964
|
1201 <!-- &interaction.mq.tarball.newsource; -->
|
belaran@964
|
1202 The pipeline starting with <command role="hg-cmd">hg locate</command> above deletes all files in
|
belaran@964
|
1203 the working directory, so that <command role="hg-cmd">hg commit</command>'s
|
belaran@964
|
1204 <option role="hg-opt-commit">--addremove</option> option can actually tell which files have
|
belaran@964
|
1205 really been removed in the newer version of the source.
|
belaran@964
|
1206 </para>
|
belaran@964
|
1207
|
belaran@964
|
1208 <para>Finally, you can apply your patches on top of the new tree.
|
belaran@964
|
1209 <!-- &interaction.mq.tarball.repush; -->
|
belaran@964
|
1210 </para>
|
belaran@964
|
1211
|
belaran@964
|
1212 </sect2>
|
belaran@964
|
1213 <sect2>
|
belaran@964
|
1214 <title>Combining entire patches</title>
|
belaran@964
|
1215 <para>\label{sec:mq:combine}
|
belaran@964
|
1216 </para>
|
belaran@964
|
1217
|
belaran@964
|
1218 <para>MQ provides a command, <command role="hg-ext-mq">qfold</command> that lets you combine entire
|
belaran@964
|
1219 patches. This <quote>folds</quote> the patches you name, in the order you name
|
belaran@964
|
1220 them, into the topmost applied patch, and concatenates their
|
belaran@964
|
1221 descriptions onto the end of its description. The patches that you
|
belaran@964
|
1222 fold must be unapplied before you fold them.
|
belaran@964
|
1223 </para>
|
belaran@964
|
1224
|
belaran@964
|
1225 <para>The order in which you fold patches matters. If your topmost applied
|
belaran@964
|
1226 patch is <literal>foo</literal>, and you <command role="hg-ext-mq">qfold</command> <literal>bar</literal> and
|
belaran@964
|
1227 <literal>quux</literal> into it, you will end up with a patch that has the same
|
belaran@964
|
1228 effect as if you applied first <literal>foo</literal>, then <literal>bar</literal>,
|
belaran@964
|
1229 followed by <literal>quux</literal>.
|
belaran@964
|
1230 </para>
|
belaran@964
|
1231
|
belaran@964
|
1232 </sect2>
|
belaran@964
|
1233 <sect2>
|
belaran@964
|
1234 <title>Merging part of one patch into another</title>
|
belaran@964
|
1235
|
belaran@964
|
1236 <para>Merging <emphasis>part</emphasis> of one patch into another is more difficult than
|
belaran@964
|
1237 combining entire patches.
|
belaran@964
|
1238 </para>
|
belaran@964
|
1239
|
belaran@964
|
1240 <para>If you want to move changes to entire files, you can use
|
belaran@964
|
1241 <command>filterdiff</command>'s <option role="cmd-opt-filterdiff">-i</option> and
|
belaran@964
|
1242 <option role="cmd-opt-filterdiff">-x</option> options to choose the modifications to snip
|
belaran@964
|
1243 out of one patch, concatenating its output onto the end of the patch
|
belaran@964
|
1244 you want to merge into. You usually won't need to modify the patch
|
belaran@964
|
1245 you've merged the changes from. Instead, MQ will report some rejected
|
belaran@964
|
1246 hunks when you <command role="hg-ext-mq">qpush</command> it (from the hunks you moved into the
|
belaran@964
|
1247 other patch), and you can simply <command role="hg-ext-mq">qrefresh</command> the patch to drop
|
belaran@964
|
1248 the duplicate hunks.
|
belaran@964
|
1249 </para>
|
belaran@964
|
1250
|
belaran@964
|
1251 <para>If you have a patch that has multiple hunks modifying a file, and you
|
belaran@964
|
1252 only want to move a few of those hunks, the job becomes more messy,
|
belaran@964
|
1253 but you can still partly automate it. Use <command>lsdiff -nvv</command> to
|
belaran@964
|
1254 print some metadata about the patch.
|
belaran@964
|
1255 <!-- &interaction.mq.tools.lsdiff; -->
|
belaran@964
|
1256 </para>
|
belaran@964
|
1257
|
belaran@964
|
1258 <para>This command prints three different kinds of number:
|
belaran@964
|
1259 </para>
|
belaran@964
|
1260 <itemizedlist>
|
belaran@964
|
1261 <listitem><para>(in the first column) a <emphasis>file number</emphasis> to identify each file
|
belaran@964
|
1262 modified in the patch;
|
belaran@964
|
1263 </para>
|
belaran@964
|
1264 </listitem>
|
belaran@964
|
1265 <listitem><para>(on the next line, indented) the line number within a modified
|
belaran@964
|
1266 file where a hunk starts; and
|
belaran@964
|
1267 </para>
|
belaran@964
|
1268 </listitem>
|
belaran@964
|
1269 <listitem><para>(on the same line) a <emphasis>hunk number</emphasis> to identify that hunk.
|
belaran@964
|
1270 </para>
|
belaran@964
|
1271 </listitem></itemizedlist>
|
belaran@964
|
1272
|
belaran@964
|
1273 <para>You'll have to use some visual inspection, and reading of the patch,
|
belaran@964
|
1274 to identify the file and hunk numbers you'll want, but you can then
|
belaran@964
|
1275 pass them to to <command>filterdiff</command>'s <option role="cmd-opt-filterdiff">--files</option>
|
belaran@964
|
1276 and <option role="cmd-opt-filterdiff">--hunks</option> options, to select exactly the file
|
belaran@964
|
1277 and hunk you want to extract.
|
belaran@964
|
1278 </para>
|
belaran@964
|
1279
|
belaran@964
|
1280 <para>Once you have this hunk, you can concatenate it onto the end of your
|
belaran@964
|
1281 destination patch and continue with the remainder of
|
belaran@964
|
1282 section <xref linkend="sec:mq:combine"/>.
|
belaran@964
|
1283 </para>
|
belaran@964
|
1284
|
belaran@964
|
1285 </sect2>
|
belaran@964
|
1286 </sect1>
|
belaran@964
|
1287 <sect1>
|
belaran@964
|
1288 <title>Differences between quilt and MQ</title>
|
belaran@964
|
1289
|
belaran@964
|
1290 <para>If you are already familiar with quilt, MQ provides a similar command
|
belaran@964
|
1291 set. There are a few differences in the way that it works.
|
belaran@964
|
1292 </para>
|
belaran@964
|
1293
|
belaran@964
|
1294 <para>You will already have noticed that most quilt commands have MQ
|
belaran@964
|
1295 counterparts that simply begin with a <quote><literal>q</literal></quote>. The exceptions
|
belaran@964
|
1296 are quilt's <literal>add</literal> and <literal>remove</literal> commands, the
|
belaran@964
|
1297 counterparts for which are the normal Mercurial <command role="hg-cmd">hg add</command> and
|
belaran@964
|
1298 <command role="hg-cmd">hg remove</command> commands. There is no MQ equivalent of the quilt
|
belaran@964
|
1299 <literal>edit</literal> command.
|
belaran@964
|
1300 </para>
|
belaran@964
|
1301
|
belaran@964
|
1302 </sect1>
|
belaran@964
|
1303 </chapter>
|
belaran@964
|
1304
|
belaran@964
|
1305 <!--
|
belaran@964
|
1306 local variables:
|
belaran@964
|
1307 sgml-parent-document: ("00book.xml" "book" "chapter")
|
belaran@964
|
1308 end:
|
belaran@964
|
1309 --> |