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