comparison en/ch08-branch.xml @ 658:b90b024729f1

WIP DocBook snapshot that all compiles. Mirabile dictu!
author Bryan O'Sullivan <bos@serpentine.com>
date Wed, 18 Feb 2009 00:22:09 -0800
parents en/ch08-branch.tex@f72b7e6cbe90
children 8fcd44708f41
comparison
equal deleted inserted replaced
657:8631da51309b 658:b90b024729f1
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
2
3 <chapter id="chap:branch">
4 <title>Managing releases and branchy development</title>
5
6 <para>Mercurial provides several mechanisms for you to manage a
7 project that is making progress on multiple fronts at once. To
8 understand these mechanisms, let's first take a brief look at a
9 fairly normal software project structure.</para>
10
11 <para>Many software projects issue periodic <quote>major</quote>
12 releases that contain substantial new features. In parallel, they
13 may issue <quote>minor</quote> releases. These are usually
14 identical to the major releases off which they're based, but with
15 a few bugs fixed.</para>
16
17 <para>In this chapter, we'll start by talking about how to keep
18 records of project milestones such as releases. We'll then
19 continue on to talk about the flow of work between different
20 phases of a project, and how Mercurial can help you to isolate and
21 manage this work.</para>
22
23 <sect1>
24 <title>Giving a persistent name to a revision</title>
25
26 <para>Once you decide that you'd like to call a particular
27 revision a <quote>release</quote>, it's a good idea to record
28 the identity of that revision. This will let you reproduce that
29 release at a later date, for whatever purpose you might need at
30 the time (reproducing a bug, porting to a new platform, etc).
31 <!-- &interaction.tag.init; --></para>
32
33 <para>Mercurial lets you give a permanent name to any revision
34 using the <command role="hg-cmd">hg tag</command> command. Not
35 surprisingly, these names are called <quote>tags</quote>. <!--
36 &interaction.tag.tag; --></para>
37
38 <para>A tag is nothing more than a <quote>symbolic name</quote>
39 for a revision. Tags exist purely for your convenience, so that
40 you have a handy permanent way to refer to a revision; Mercurial
41 doesn't interpret the tag names you use in any way. Neither
42 does Mercurial place any restrictions on the name of a tag,
43 beyond a few that are necessary to ensure that a tag can be
44 parsed unambiguously. A tag name cannot contain any of the
45 following characters:</para>
46 <itemizedlist>
47 <listitem><para>Colon (ASCII 58,
48 <quote><literal>:</literal></quote>)</para>
49 </listitem>
50 <listitem><para>Carriage return (ASCII 13,
51 <quote><literal>\r</literal></quote>)</para>
52 </listitem>
53 <listitem><para>Newline (ASCII 10,
54 <quote><literal>\n</literal></quote>)</para>
55 </listitem></itemizedlist>
56
57 <para>You can use the <command role="hg-cmd">hg tags</command>
58 command to display the tags present in your repository. In the
59 output, each tagged revision is identified first by its name,
60 then by revision number, and finally by the unique hash of the
61 revision. <!-- &interaction.tag.tags; --> Notice that
62 <literal>tip</literal> is listed in the output of <command
63 role="hg-cmd">hg tags</command>. The <literal>tip</literal>
64 tag is a special <quote>floating</quote> tag, which always
65 identifies the newest revision in the repository.</para>
66
67 <para>In the output of the <command role="hg-cmd">hg
68 tags</command> command, tags are listed in reverse order, by
69 revision number. This usually means that recent tags are listed
70 before older tags. It also means that <literal>tip</literal> is
71 always going to be the first tag listed in the output of
72 <command role="hg-cmd">hg tags</command>.</para>
73
74 <para>When you run <command role="hg-cmd">hg log</command>, if it
75 displays a revision that has tags associated with it, it will
76 print those tags. <!-- &interaction.tag.log; --></para>
77
78 <para>Any time you need to provide a revision ID to a Mercurial
79 command, the command will accept a tag name in its place.
80 Internally, Mercurial will translate your tag name into the
81 corresponding revision ID, then use that. <!--
82 &interaction.tag.log.v1.0; --></para>
83
84 <para>There's no limit on the number of tags you can have in a
85 repository, or on the number of tags that a single revision can
86 have. As a practical matter, it's not a great idea to have
87 <quote>too many</quote> (a number which will vary from project
88 to project), simply because tags are supposed to help you to
89 find revisions. If you have lots of tags, the ease of using
90 them to identify revisions diminishes rapidly.</para>
91
92 <para>For example, if your project has milestones as frequent as
93 every few days, it's perfectly reasonable to tag each one of
94 those. But if you have a continuous build system that makes
95 sure every revision can be built cleanly, you'd be introducing a
96 lot of noise if you were to tag every clean build. Instead, you
97 could tag failed builds (on the assumption that they're rare!),
98 or simply not use tags to track buildability.</para>
99
100 <para>If you want to remove a tag that you no longer want, use
101 <command role="hg-cmd">hg tag --remove</command>. <!--
102 &interaction.tag.remove; --> You can also modify a tag at any
103 time, so that it identifies a different revision, by simply
104 issuing a new <command role="hg-cmd">hg tag</command> command.
105 You'll have to use the <option role="hg-opt-tag">-f</option>
106 option to tell Mercurial that you <emphasis>really</emphasis>
107 want to update the tag. <!-- &interaction.tag.replace; --> There
108 will still be a permanent record of the previous identity of the
109 tag, but Mercurial will no longer use it. There's thus no
110 penalty to tagging the wrong revision; all you have to do is
111 turn around and tag the correct revision once you discover your
112 error.</para>
113
114 <para>Mercurial stores tags in a normal revision-controlled file
115 in your repository. If you've created any tags, you'll find
116 them in a file named <filename
117 role="special">.hgtags</filename>. When you run the <command
118 role="hg-cmd">hg tag</command> command, Mercurial modifies
119 this file, then automatically commits the change to it. This
120 means that every time you run <command role="hg-cmd">hg
121 tag</command>, you'll see a corresponding changeset in the
122 output of <command role="hg-cmd">hg log</command>. <!--
123 &interaction.tag.tip; --></para>
124
125 <sect2>
126 <title>Handling tag conflicts during a merge</title>
127
128 <para>You won't often need to care about the <filename
129 role="special">.hgtags</filename> file, but it sometimes
130 makes its presence known during a merge. The format of the
131 file is simple: it consists of a series of lines. Each line
132 starts with a changeset hash, followed by a space, followed by
133 the name of a tag.</para>
134
135 <para>If you're resolving a conflict in the <filename
136 role="special">.hgtags</filename> file during a merge,
137 there's one twist to modifying the <filename
138 role="special">.hgtags</filename> file: when Mercurial is
139 parsing the tags in a repository, it
140 <emphasis>never</emphasis> reads the working copy of the
141 <filename role="special">.hgtags</filename> file. Instead, it
142 reads the <emphasis>most recently committed</emphasis>
143 revision of the file.</para>
144
145 <para>An unfortunate consequence of this design is that you
146 can't actually verify that your merged <filename
147 role="special">.hgtags</filename> file is correct until
148 <emphasis>after</emphasis> you've committed a change. So if
149 you find yourself resolving a conflict on <filename
150 role="special">.hgtags</filename> during a merge, be sure to
151 run <command role="hg-cmd">hg tags</command> after you commit.
152 If it finds an error in the <filename
153 role="special">.hgtags</filename> file, it will report the
154 location of the error, which you can then fix and commit. You
155 should then run <command role="hg-cmd">hg tags</command>
156 again, just to be sure that your fix is correct.</para>
157
158 </sect2>
159 <sect2>
160 <title>Tags and cloning</title>
161
162 <para>You may have noticed that the <command role="hg-cmd">hg
163 clone</command> command has a <option
164 role="hg-opt-clone">-r</option> option that lets you clone
165 an exact copy of the repository as of a particular changeset.
166 The new clone will not contain any project history that comes
167 after the revision you specified. This has an interaction
168 with tags that can surprise the unwary.</para>
169
170 <para>Recall that a tag is stored as a revision to the <filename
171 role="special">.hgtags</filename> file, so that when you
172 create a tag, the changeset in which it's recorded necessarily
173 refers to an older changeset. When you run <command
174 role="hg-cmd">hg clone -r foo</command> to clone a
175 repository as of tag <literal>foo</literal>, the new clone
176 <emphasis>will not contain the history that created the
177 tag</emphasis> that you used to clone the repository. The
178 result is that you'll get exactly the right subset of the
179 project's history in the new repository, but
180 <emphasis>not</emphasis> the tag you might have
181 expected.</para>
182
183 </sect2>
184 <sect2>
185 <title>When permanent tags are too much</title>
186
187 <para>Since Mercurial's tags are revision controlled and carried
188 around with a project's history, everyone you work with will
189 see the tags you create. But giving names to revisions has
190 uses beyond simply noting that revision
191 <literal>4237e45506ee</literal> is really
192 <literal>v2.0.2</literal>. If you're trying to track down a
193 subtle bug, you might want a tag to remind you of something
194 like <quote>Anne saw the symptoms with this
195 revision</quote>.</para>
196
197 <para>For cases like this, what you might want to use are
198 <emphasis>local</emphasis> tags. You can create a local tag
199 with the <option role="hg-opt-tag">-l</option> option to the
200 <command role="hg-cmd">hg tag</command> command. This will
201 store the tag in a file called <filename
202 role="special">.hg/localtags</filename>. Unlike <filename
203 role="special">.hgtags</filename>, <filename
204 role="special">.hg/localtags</filename> is not revision
205 controlled. Any tags you create using <option
206 role="hg-opt-tag">-l</option> remain strictly local to the
207 repository you're currently working in.</para>
208
209 </sect2>
210 </sect1>
211 <sect1>
212 <title>The flow of changes&emdash;big picture vs. little</title>
213
214 <para>To return to the outline I sketched at the beginning of a
215 chapter, let's think about a project that has multiple
216 concurrent pieces of work under development at once.</para>
217
218 <para>There might be a push for a new <quote>main</quote> release;
219 a new minor bugfix release to the last main release; and an
220 unexpected <quote>hot fix</quote> to an old release that is now
221 in maintenance mode.</para>
222
223 <para>The usual way people refer to these different concurrent
224 directions of development is as <quote>branches</quote>.
225 However, we've already seen numerous times that Mercurial treats
226 <emphasis>all of history</emphasis> as a series of branches and
227 merges. Really, what we have here is two ideas that are
228 peripherally related, but which happen to share a name.</para>
229 <itemizedlist>
230 <listitem><para><quote>Big picture</quote> branches represent
231 the sweep of a project's evolution; people give them names,
232 and talk about them in conversation.</para>
233 </listitem>
234 <listitem><para><quote>Little picture</quote> branches are
235 artefacts of the day-to-day activity of developing and
236 merging changes. They expose the narrative of how the code
237 was developed.</para>
238 </listitem></itemizedlist>
239
240 </sect1>
241 <sect1>
242 <title>Managing big-picture branches in repositories</title>
243
244 <para>The easiest way to isolate a <quote>big picture</quote>
245 branch in Mercurial is in a dedicated repository. If you have
246 an existing shared repository&emdash;let's call it
247 <literal>myproject</literal>&emdash;that reaches a
248 <quote>1.0</quote> milestone, you can start to prepare for
249 future maintenance releases on top of version 1.0 by tagging the
250 revision from which you prepared the 1.0 release. <!--
251 &interaction.branch-repo.tag; --> You can then clone a new
252 shared <literal>myproject-1.0.1</literal> repository as of that
253 tag. <!-- &interaction.branch-repo.clone; --></para>
254
255 <para>Afterwards, if someone needs to work on a bug fix that ought
256 to go into an upcoming 1.0.1 minor release, they clone the
257 <literal>myproject-1.0.1</literal> repository, make their
258 changes, and push them back. <!--
259 &interaction.branch-repo.bugfix; --> Meanwhile, development for
260 the next major release can continue, isolated and unabated, in
261 the <literal>myproject</literal> repository. <!--
262 &interaction.branch-repo.new; --></para>
263
264 </sect1>
265 <sect1>
266 <title>Don't repeat yourself: merging across branches</title>
267
268 <para>In many cases, if you have a bug to fix on a maintenance
269 branch, the chances are good that the bug exists on your
270 project's main branch (and possibly other maintenance branches,
271 too). It's a rare developer who wants to fix the same bug
272 multiple times, so let's look at a few ways that Mercurial can
273 help you to manage these bugfixes without duplicating your
274 work.</para>
275
276 <para>In the simplest instance, all you need to do is pull changes
277 from your maintenance branch into your local clone of the target
278 branch. <!-- &interaction.branch-repo.pull; --> You'll then need
279 to merge the heads of the two branches, and push back to the
280 main branch. <!-- &interaction.branch-repo.merge; --></para>
281
282 </sect1>
283 <sect1>
284 <title>Naming branches within one repository</title>
285
286 <para>In most instances, isolating branches in repositories is the
287 right approach. Its simplicity makes it easy to understand; and
288 so it's hard to make mistakes. There's a one-to-one
289 relationship between branches you're working in and directories
290 on your system. This lets you use normal (non-Mercurial-aware)
291 tools to work on files within a branch/repository.</para>
292
293 <para>If you're more in the <quote>power user</quote> category
294 (<emphasis>and</emphasis> your collaborators are too), there is
295 an alternative way of handling branches that you can consider.
296 I've already mentioned the human-level distinction between
297 <quote>small picture</quote> and <quote>big picture</quote>
298 branches. While Mercurial works with multiple <quote>small
299 picture</quote> branches in a repository all the time (for
300 example after you pull changes in, but before you merge them),
301 it can <emphasis>also</emphasis> work with multiple <quote>big
302 picture</quote> branches.</para>
303
304 <para>The key to working this way is that Mercurial lets you
305 assign a persistent <emphasis>name</emphasis> to a branch.
306 There always exists a branch named <literal>default</literal>.
307 Even before you start naming branches yourself, you can find
308 traces of the <literal>default</literal> branch if you look for
309 them.</para>
310
311 <para>As an example, when you run the <command role="hg-cmd">hg
312 commit</command> command, and it pops up your editor so that
313 you can enter a commit message, look for a line that contains
314 the text <quote><literal>HG: branch default</literal></quote> at
315 the bottom. This is telling you that your commit will occur on
316 the branch named <literal>default</literal>.</para>
317
318 <para>To start working with named branches, use the <command
319 role="hg-cmd">hg branches</command> command. This command
320 lists the named branches already present in your repository,
321 telling you which changeset is the tip of each. <!--
322 &interaction.branch-named.branches; --> Since you haven't
323 created any named branches yet, the only one that exists is
324 <literal>default</literal>.</para>
325
326 <para>To find out what the <quote>current</quote> branch is, run
327 the <command role="hg-cmd">hg branch</command> command, giving
328 it no arguments. This tells you what branch the parent of the
329 current changeset is on. <!-- &interaction.branch-named.branch;
330 --></para>
331
332 <para>To create a new branch, run the <command role="hg-cmd">hg
333 branch</command> command again. This time, give it one
334 argument: the name of the branch you want to create. <!--
335 &interaction.branch-named.create; --></para>
336
337 <para>After you've created a branch, you might wonder what effect
338 the <command role="hg-cmd">hg branch</command> command has had.
339 What do the <command role="hg-cmd">hg status</command> and
340 <command role="hg-cmd">hg tip</command> commands report? <!--
341 &interaction.branch-named.status; --> Nothing has changed in the
342 working directory, and there's been no new history created. As
343 this suggests, running the <command role="hg-cmd">hg
344 branch</command> command has no permanent effect; it only
345 tells Mercurial what branch name to use the
346 <emphasis>next</emphasis> time you commit a changeset.</para>
347
348 <para>When you commit a change, Mercurial records the name of the
349 branch on which you committed. Once you've switched from the
350 <literal>default</literal> branch to another and committed,
351 you'll see the name of the new branch show up in the output of
352 <command role="hg-cmd">hg log</command>, <command
353 role="hg-cmd">hg tip</command>, and other commands that
354 display the same kind of output. <!--
355 &interaction.branch-named.commit; --> The <command
356 role="hg-cmd">hg log</command>-like commands will print the
357 branch name of every changeset that's not on the
358 <literal>default</literal> branch. As a result, if you never
359 use named branches, you'll never see this information.</para>
360
361 <para>Once you've named a branch and committed a change with that
362 name, every subsequent commit that descends from that change
363 will inherit the same branch name. You can change the name of a
364 branch at any time, using the <command role="hg-cmd">hg
365 branch</command> command. <!--
366 &interaction.branch-named.rebranch; --> In practice, this is
367 something you won't do very often, as branch names tend to have
368 fairly long lifetimes. (This isn't a rule, just an
369 observation.)</para>
370
371 </sect1>
372 <sect1>
373 <title>Dealing with multiple named branches in a
374 repository</title>
375
376 <para>If you have more than one named branch in a repository,
377 Mercurial will remember the branch that your working directory
378 on when you start a command like <command role="hg-cmd">hg
379 update</command> or <command role="hg-cmd">hg pull
380 -u</command>. It will update the working directory to the tip
381 of this branch, no matter what the <quote>repo-wide</quote> tip
382 is. To update to a revision that's on a different named branch,
383 you may need to use the <option role="hg-opt-update">-C</option>
384 option to <command role="hg-cmd">hg update</command>.</para>
385
386 <para>This behaviour is a little subtle, so let's see it in
387 action. First, let's remind ourselves what branch we're
388 currently on, and what branches are in our repository. <!--
389 &interaction.branch-named.parents; --> We're on the
390 <literal>bar</literal> branch, but there also exists an older
391 <command role="hg-cmd">hg foo</command> branch.</para>
392
393 <para>We can <command role="hg-cmd">hg update</command> back and
394 forth between the tips of the <literal>foo</literal> and
395 <literal>bar</literal> branches without needing to use the
396 <option role="hg-opt-update">-C</option> option, because this
397 only involves going backwards and forwards linearly through our
398 change history. <!-- &interaction.branch-named.update-switchy;
399 --></para>
400
401 <para>If we go back to the <literal>foo</literal> branch and then
402 run <command role="hg-cmd">hg update</command>, it will keep us
403 on <literal>foo</literal>, not move us to the tip of
404 <literal>bar</literal>. <!--
405 &interaction.branch-named.update-nothing; --></para>
406
407 <para>Committing a new change on the <literal>foo</literal> branch
408 introduces a new head. <!--
409 &interaction.branch-named.foo-commit; --></para>
410
411 </sect1>
412 <sect1>
413 <title>Branch names and merging</title>
414
415 <para>As you've probably noticed, merges in Mercurial are not
416 symmetrical. Let's say our repository has two heads, 17 and 23.
417 If I <command role="hg-cmd">hg update</command> to 17 and then
418 <command role="hg-cmd">hg merge</command> with 23, Mercurial
419 records 17 as the first parent of the merge, and 23 as the
420 second. Whereas if I <command role="hg-cmd">hg update</command>
421 to 23 and then <command role="hg-cmd">hg merge</command> with
422 17, it records 23 as the first parent, and 17 as the
423 second.</para>
424
425 <para>This affects Mercurial's choice of branch name when you
426 merge. After a merge, Mercurial will retain the branch name of
427 the first parent when you commit the result of the merge. If
428 your first parent's branch name is <literal>foo</literal>, and
429 you merge with <literal>bar</literal>, the branch name will
430 still be <literal>foo</literal> after you merge.</para>
431
432 <para>It's not unusual for a repository to contain multiple heads,
433 each with the same branch name. Let's say I'm working on the
434 <literal>foo</literal> branch, and so are you. We commit
435 different changes; I pull your changes; I now have two heads,
436 each claiming to be on the <literal>foo</literal> branch. The
437 result of a merge will be a single head on the
438 <literal>foo</literal> branch, as you might hope.</para>
439
440 <para>But if I'm working on the <literal>bar</literal> branch, and
441 I merge work from the <literal>foo</literal> branch, the result
442 will remain on the <literal>bar</literal> branch. <!--
443 &interaction.branch-named.merge; --></para>
444
445 <para>To give a more concrete example, if I'm working on the
446 <literal>bleeding-edge</literal> branch, and I want to bring in
447 the latest fixes from the <literal>stable</literal> branch,
448 Mercurial will choose the <quote>right</quote>
449 (<literal>bleeding-edge</literal>) branch name when I pull and
450 merge from <literal>stable</literal>.</para>
451
452 </sect1>
453 <sect1>
454 <title>Branch naming is generally useful</title>
455
456 <para>You shouldn't think of named branches as applicable only to
457 situations where you have multiple long-lived branches
458 cohabiting in a single repository. They're very useful even in
459 the one-branch-per-repository case.</para>
460
461 <para>In the simplest case, giving a name to each branch gives you
462 a permanent record of which branch a changeset originated on.
463 This gives you more context when you're trying to follow the
464 history of a long-lived branchy project.</para>
465
466 <para>If you're working with shared repositories, you can set up a
467 <literal role="hook">pretxnchangegroup</literal> hook on each
468 that will block incoming changes that have the
469 <quote>wrong</quote> branch name. This provides a simple, but
470 effective, defence against people accidentally pushing changes
471 from a <quote>bleeding edge</quote> branch to a
472 <quote>stable</quote> branch. Such a hook might look like this
473 inside the shared repo's <filename role="special">
474 /.hgrc</filename>.</para>
475 <programlisting>[hooks] pretxnchangegroup.branch = hg heads
476 --template '{branches} ' | grep mybranch</programlisting>
477
478 </sect1>
479 </chapter>
480
481 <!--
482 local variables:
483 sgml-parent-document: ("00book.xml" "book" "chapter")
484 end:
485 -->