hgbook

view en/ch05-daily.xml @ 559:b90b024729f1

WIP DocBook snapshot that all compiles. Mirabile dictu!
author Bryan O'Sullivan <bos@serpentine.com>
date Wed Feb 18 00:22:09 2009 -0800 (2009-02-18)
parents en/ch05-daily.tex@f72b7e6cbe90
children 8fcd44708f41
line source
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
3 <chapter id="chap:daily">
4 <title>Mercurial in daily use</title>
6 <sect1>
7 <title>Telling Mercurial which files to track</title>
9 <para>Mercurial does not work with files in your repository unless
10 you tell it to manage them. The <command role="hg-cmd">hg
11 status</command> command will tell you which files Mercurial
12 doesn't know about; it uses a
13 <quote><literal>?</literal></quote> to display such
14 files.</para>
16 <para>To tell Mercurial to track a file, use the <command
17 role="hg-cmd">hg add</command> command. Once you have added a
18 file, the entry in the output of <command role="hg-cmd">hg
19 status</command> for that file changes from
20 <quote><literal>?</literal></quote> to
21 <quote><literal>A</literal></quote>. <!--
22 &interaction.daily.files.add; --></para>
24 <para>After you run a <command role="hg-cmd">hg commit</command>,
25 the files that you added before the commit will no longer be
26 listed in the output of <command role="hg-cmd">hg
27 status</command>. The reason for this is that <command
28 role="hg-cmd">hg status</command> only tells you about
29 <quote>interesting</quote> files&emdash;those that you have
30 modified or told Mercurial to do something with&emdash;by
31 default. If you have a repository that contains thousands of
32 files, you will rarely want to know about files that Mercurial
33 is tracking, but that have not changed. (You can still get this
34 information; we'll return to this later.)</para>
36 <para>Once you add a file, Mercurial doesn't do anything with it
37 immediately. Instead, it will take a snapshot of the file's
38 state the next time you perform a commit. It will then continue
39 to track the changes you make to the file every time you commit,
40 until you remove the file.</para>
42 <sect2>
43 <title>Explicit versus implicit file naming</title>
45 <para>A useful behaviour that Mercurial has is that if you pass
46 the name of a directory to a command, every Mercurial command
47 will treat this as <quote>I want to operate on every file in
48 this directory and its subdirectories</quote>. <!--
49 &interaction.daily.files.add-dir; --> Notice in this example
50 that Mercurial printed the names of the files it added,
51 whereas it didn't do so when we added the file named
52 <filename>a</filename> in the earlier example.</para>
54 <para>What's going on is that in the former case, we explicitly
55 named the file to add on the command line, so the assumption
56 that Mercurial makes in such cases is that you know what you
57 were doing, and it doesn't print any output.</para>
59 <para>However, when we <emphasis>imply</emphasis> the names of
60 files by giving the name of a directory, Mercurial takes the
61 extra step of printing the name of each file that it does
62 something with. This makes it more clear what is happening,
63 and reduces the likelihood of a silent and nasty surprise.
64 This behaviour is common to most Mercurial commands.</para>
66 </sect2>
67 <sect2>
68 <title>Aside: Mercurial tracks files, not directories</title>
70 <para>Mercurial does not track directory information. Instead,
71 it tracks the path to a file. Before creating a file, it
72 first creates any missing directory components of the path.
73 After it deletes a file, it then deletes any empty directories
74 that were in the deleted file's path. This sounds like a
75 trivial distinction, but it has one minor practical
76 consequence: it is not possible to represent a completely
77 empty directory in Mercurial.</para>
79 <para>Empty directories are rarely useful, and there are
80 unintrusive workarounds that you can use to achieve an
81 appropriate effect. The developers of Mercurial thus felt
82 that the complexity that would be required to manage empty
83 directories was not worth the limited benefit this feature
84 would bring.</para>
86 <para>If you need an empty directory in your repository, there
87 are a few ways to achieve this. One is to create a directory,
88 then <command role="hg-cmd">hg add</command> a
89 <quote>hidden</quote> file to that directory. On Unix-like
90 systems, any file name that begins with a period
91 (<quote><literal>.</literal></quote>) is treated as hidden by
92 most commands and GUI tools. This approach is illustrated
93 below.</para>
95 <!-- &interaction.daily.files.hidden; -->
97 <para>Another way to tackle a need for an empty directory is to
98 simply create one in your automated build scripts before they
99 will need it.</para>
101 </sect2>
102 </sect1>
103 <sect1>
104 <title>How to stop tracking a file</title>
106 <para>Once you decide that a file no longer belongs in your
107 repository, use the <command role="hg-cmd">hg remove</command>
108 command; this deletes the file, and tells Mercurial to stop
109 tracking it. A removed file is represented in the output of
110 <command role="hg-cmd">hg status</command> with a
111 <quote><literal>R</literal></quote>. <!--
112 &interaction.daily.files.remove; --></para>
114 <para>After you <command role="hg-cmd">hg remove</command> a file,
115 Mercurial will no longer track changes to that file, even if you
116 recreate a file with the same name in your working directory.
117 If you do recreate a file with the same name and want Mercurial
118 to track the new file, simply <command role="hg-cmd">hg
119 add</command> it. Mercurial will know that the newly added
120 file is not related to the old file of the same name.</para>
122 <sect2>
123 <title>Removing a file does not affect its history</title>
125 <para>It is important to understand that removing a file has
126 only two effects.</para>
127 <itemizedlist>
128 <listitem><para>It removes the current version of the file
129 from the working directory.</para>
130 </listitem>
131 <listitem><para>It stops Mercurial from tracking changes to
132 the file, from the time of the next commit.</para>
133 </listitem></itemizedlist>
134 <para>Removing a file <emphasis>does not</emphasis> in any way
135 alter the <emphasis>history</emphasis> of the file.</para>
137 <para>If you update the working directory to a changeset in
138 which a file that you have removed was still tracked, it will
139 reappear in the working directory, with the contents it had
140 when you committed that changeset. If you then update the
141 working directory to a later changeset, in which the file had
142 been removed, Mercurial will once again remove the file from
143 the working directory.</para>
145 </sect2>
146 <sect2>
147 <title>Missing files</title>
149 <para>Mercurial considers a file that you have deleted, but not
150 used <command role="hg-cmd">hg remove</command> to delete, to
151 be <emphasis>missing</emphasis>. A missing file is
152 represented with <quote><literal>!</literal></quote> in the
153 output of <command role="hg-cmd">hg status</command>.
154 Mercurial commands will not generally do anything with missing
155 files. <!-- &interaction.daily.files.missing; --></para>
157 <para>If your repository contains a file that <command
158 role="hg-cmd">hg status</command> reports as missing, and
159 you want the file to stay gone, you can run <command
160 role="hg-cmd">hg remove <option
161 role="hg-opt-remove">--after</option></command> at any
162 time later on, to tell Mercurial that you really did mean to
163 remove the file. <!-- &interaction.daily.files.remove-after;
164 --></para>
166 <para>On the other hand, if you deleted the missing file by
167 accident, give <command role="hg-cmd">hg revert</command> the
168 name of the file to recover. It will reappear, in unmodified
169 form.</para>
171 <!-- &interaction.daily.files.recover-missing; -->
173 </sect2>
174 <sect2>
175 <title>Aside: why tell Mercurial explicitly to remove a
176 file?</title>
178 <para>You might wonder why Mercurial requires you to explicitly
179 tell it that you are deleting a file. Early during the
180 development of Mercurial, it let you delete a file however you
181 pleased; Mercurial would notice the absence of the file
182 automatically when you next ran a <command role="hg-cmd">hg
183 commit</command>, and stop tracking the file. In practice,
184 this made it too easy to accidentally remove a file without
185 noticing.</para>
187 </sect2>
188 <sect2>
189 <title>Useful shorthand&emdash;adding and removing files in one
190 step</title>
192 <para>Mercurial offers a combination command, <command
193 role="hg-cmd">hg addremove</command>, that adds untracked
194 files and marks missing files as removed. <!--
195 &interaction.daily.files.addremove; --> The <command
196 role="hg-cmd">hg commit</command> command also provides a
197 <option role="hg-opt-commit">-A</option> option that performs
198 this same add-and-remove, immediately followed by a commit.
199 <!-- &interaction.daily.files.commit-addremove; --></para>
201 </sect2>
202 </sect1>
203 <sect1>
204 <title>Copying files</title>
206 <para>Mercurial provides a <command role="hg-cmd">hg
207 copy</command> command that lets you make a new copy of a
208 file. When you copy a file using this command, Mercurial makes
209 a record of the fact that the new file is a copy of the original
210 file. It treats these copied files specially when you merge
211 your work with someone else's.</para>
213 <sect2>
214 <title>The results of copying during a merge</title>
216 <para>What happens during a merge is that changes
217 <quote>follow</quote> a copy. To best illustrate what this
218 means, let's create an example. We'll start with the usual
219 tiny repository that contains a single file. <!--
220 &interaction.daily.copy.init; --> We need to do some work in
221 parallel, so that we'll have something to merge. So let's
222 clone our repository. <!-- &interaction.daily.copy.clone; -->
223 Back in our initial repository, let's use the <command
224 role="hg-cmd">hg copy</command> command to make a copy of
225 the first file we created. <!-- &interaction.daily.copy.copy;
226 --></para>
228 <para>If we look at the output of the <command role="hg-cmd">hg
229 status</command> command afterwards, the copied file looks
230 just like a normal added file. <!--
231 &interaction.daily.copy.status; --> But if we pass the <option
232 role="hg-opt-status">-C</option> option to <command
233 role="hg-cmd">hg status</command>, it prints another line of
234 output: this is the file that our newly-added file was copied
235 <emphasis>from</emphasis>. <!--
236 &interaction.daily.copy.status-copy; --></para>
238 <para>Now, back in the repository we cloned, let's make a change
239 in parallel. We'll add a line of content to the original file
240 that we created. <!-- &interaction.daily.copy.other; --> Now
241 we have a modified <filename>file</filename> in this
242 repository. When we pull the changes from the first
243 repository, and merge the two heads, Mercurial will propagate
244 the changes that we made locally to <filename>file</filename>
245 into its copy, <filename>new-file</filename>. <!--
246 &interaction.daily.copy.merge; --></para>
248 </sect2>
249 <sect2 id="sec:daily:why-copy">
250 <title>Why should changes follow copies?</title>
252 <para>This behaviour, of changes to a file propagating out to
253 copies of the file, might seem esoteric, but in most cases
254 it's highly desirable.</para>
256 <para>First of all, remember that this propagation
257 <emphasis>only</emphasis> happens when you merge. So if you
258 <command role="hg-cmd">hg copy</command> a file, and
259 subsequently modify the original file during the normal course
260 of your work, nothing will happen.</para>
262 <para>The second thing to know is that modifications will only
263 propagate across a copy as long as the repository that you're
264 pulling changes from <emphasis>doesn't know</emphasis> about
265 the copy.</para>
267 <para>The reason that Mercurial does this is as follows. Let's
268 say I make an important bug fix in a source file, and commit
269 my changes. Meanwhile, you've decided to <command
270 role="hg-cmd">hg copy</command> the file in your repository,
271 without knowing about the bug or having seen the fix, and you
272 have started hacking on your copy of the file.</para>
274 <para>If you pulled and merged my changes, and Mercurial
275 <emphasis>didn't</emphasis> propagate changes across copies,
276 your source file would now contain the bug, and unless you
277 remembered to propagate the bug fix by hand, the bug would
278 <emphasis>remain</emphasis> in your copy of the file.</para>
280 <para>By automatically propagating the change that fixed the bug
281 from the original file to the copy, Mercurial prevents this
282 class of problem. To my knowledge, Mercurial is the
283 <emphasis>only</emphasis> revision control system that
284 propagates changes across copies like this.</para>
286 <para>Once your change history has a record that the copy and
287 subsequent merge occurred, there's usually no further need to
288 propagate changes from the original file to the copied file,
289 and that's why Mercurial only propagates changes across copies
290 until this point, and no further.</para>
292 </sect2>
293 <sect2>
294 <title>How to make changes <emphasis>not</emphasis> follow a
295 copy</title>
297 <para>If, for some reason, you decide that this business of
298 automatically propagating changes across copies is not for
299 you, simply use your system's normal file copy command (on
300 Unix-like systems, that's <command>cp</command>) to make a
301 copy of a file, then <command role="hg-cmd">hg add</command>
302 the new copy by hand. Before you do so, though, please do
303 reread section <xref linkend="sec:daily:why-copy"/>, and make
304 an informed
305 decision that this behaviour is not appropriate to your
306 specific case.</para>
308 </sect2>
309 <sect2>
310 <title>Behaviour of the <command role="hg-cmd">hg copy</command>
311 command</title>
313 <para>When you use the <command role="hg-cmd">hg copy</command>
314 command, Mercurial makes a copy of each source file as it
315 currently stands in the working directory. This means that if
316 you make some modifications to a file, then <command
317 role="hg-cmd">hg copy</command> it without first having
318 committed those changes, the new copy will also contain the
319 modifications you have made up until that point. (I find this
320 behaviour a little counterintuitive, which is why I mention it
321 here.)</para>
323 <para>The <command role="hg-cmd">hg copy</command> command acts
324 similarly to the Unix <command>cp</command> command (you can
325 use the <command role="hg-cmd">hg cp</command> alias if you
326 prefer). The last argument is the
327 <emphasis>destination</emphasis>, and all prior arguments are
328 <emphasis>sources</emphasis>. If you pass it a single file as
329 the source, and the destination does not exist, it creates a
330 new file with that name. <!-- &interaction.daily.copy.simple;
331 --> If the destination is a directory, Mercurial copies its
332 sources into that directory. <!--
333 &interaction.daily.copy.dir-dest; --> Copying a directory is
334 recursive, and preserves the directory structure of the
335 source. <!-- &interaction.daily.copy.dir-src; --> If the
336 source and destination are both directories, the source tree
337 is recreated in the destination directory. <!--
338 &interaction.daily.copy.dir-src-dest; --></para>
340 <para>As with the <command role="hg-cmd">hg rename</command>
341 command, if you copy a file manually and then want Mercurial
342 to know that you've copied the file, simply use the <option
343 role="hg-opt-copy">--after</option> option to <command
344 role="hg-cmd">hg copy</command>. <!--
345 &interaction.daily.copy.after; --></para>
347 </sect2>
348 </sect1>
349 <sect1>
350 <title>Renaming files</title>
352 <para>It's rather more common to need to rename a file than to
353 make a copy of it. The reason I discussed the <command
354 role="hg-cmd">hg copy</command> command before talking about
355 renaming files is that Mercurial treats a rename in essentially
356 the same way as a copy. Therefore, knowing what Mercurial does
357 when you copy a file tells you what to expect when you rename a
358 file.</para>
360 <para>When you use the <command role="hg-cmd">hg rename</command>
361 command, Mercurial makes a copy of each source file, then
362 deletes it and marks the file as removed. <!--
363 &interaction.daily.rename.rename; --> The <command
364 role="hg-cmd">hg status</command> command shows the newly
365 copied file as added, and the copied-from file as removed. <!--
366 &interaction.daily.rename.status; --> As with the results of a
367 <command role="hg-cmd">hg copy</command>, we must use the
368 <option role="hg-opt-status">-C</option> option to <command
369 role="hg-cmd">hg status</command> to see that the added file
370 is really being tracked by Mercurial as a copy of the original,
371 now removed, file. <!-- &interaction.daily.rename.status-copy;
372 --></para>
374 <para>As with <command role="hg-cmd">hg remove</command> and
375 <command role="hg-cmd">hg copy</command>, you can tell Mercurial
376 about a rename after the fact using the <option
377 role="hg-opt-rename">--after</option> option. In most other
378 respects, the behaviour of the <command role="hg-cmd">hg
379 rename</command> command, and the options it accepts, are
380 similar to the <command role="hg-cmd">hg copy</command>
381 command.</para>
383 <sect2>
384 <title>Renaming files and merging changes</title>
386 <para>Since Mercurial's rename is implemented as
387 copy-and-remove, the same propagation of changes happens when
388 you merge after a rename as after a copy.</para>
390 <para>If I modify a file, and you rename it to a new name, and
391 then we merge our respective changes, my modifications to the
392 file under its original name will be propagated into the file
393 under its new name. (This is something you might expect to
394 <quote>simply work,</quote> but not all revision control
395 systems actually do this.)</para>
397 <para>Whereas having changes follow a copy is a feature where
398 you can perhaps nod and say <quote>yes, that might be
399 useful,</quote> it should be clear that having them follow a
400 rename is definitely important. Without this facility, it
401 would simply be too easy for changes to become orphaned when
402 files are renamed.</para>
404 </sect2>
405 <sect2>
406 <title>Divergent renames and merging</title>
408 <para>The case of diverging names occurs when two developers
409 start with a file&emdash;let's call it
410 <filename>foo</filename>&emdash;in their respective
411 repositories.</para>
413 <para><!-- &interaction.rename.divergent.clone; --> Anne renames
414 the file to <filename>bar</filename>. <!--
415 &interaction.rename.divergent.rename.anne; --> Meanwhile, Bob
416 renames it to <filename>quux</filename>. <!--
417 &interaction.rename.divergent.rename.bob; --></para>
419 <para>I like to think of this as a conflict because each
420 developer has expressed different intentions about what the
421 file ought to be named.</para>
423 <para>What do you think should happen when they merge their
424 work? Mercurial's actual behaviour is that it always preserves
425 <emphasis>both</emphasis> names when it merges changesets that
426 contain divergent renames. <!--
427 &interaction.rename.divergent.merge; --></para>
429 <para>Notice that Mercurial does warn about the divergent
430 renames, but it leaves it up to you to do something about the
431 divergence after the merge.</para>
433 </sect2>
434 <sect2>
435 <title>Convergent renames and merging</title>
437 <para>Another kind of rename conflict occurs when two people
438 choose to rename different <emphasis>source</emphasis> files
439 to the same <emphasis>destination</emphasis>. In this case,
440 Mercurial runs its normal merge machinery, and lets you guide
441 it to a suitable resolution.</para>
443 </sect2>
444 <sect2>
445 <title>Other name-related corner cases</title>
447 <para>Mercurial has a longstanding bug in which it fails to
448 handle a merge where one side has a file with a given name,
449 while another has a directory with the same name. This is
450 documented as <ulink role="hg-bug"
451 url="http://www.selenic.com/mercurial/bts/issue29">issue
452 29</ulink>. <!-- &interaction.issue29.go; --></para>
454 </sect2>
455 </sect1>
456 <sect1>
457 <title>Recovering from mistakes</title>
459 <para>Mercurial has some useful commands that will help you to
460 recover from some common mistakes.</para>
462 <para>The <command role="hg-cmd">hg revert</command> command lets
463 you undo changes that you have made to your working directory.
464 For example, if you <command role="hg-cmd">hg add</command> a
465 file by accident, just run <command role="hg-cmd">hg
466 revert</command> with the name of the file you added, and
467 while the file won't be touched in any way, it won't be tracked
468 for adding by Mercurial any longer, either. You can also use
469 <command role="hg-cmd">hg revert</command> to get rid of
470 erroneous changes to a file.</para>
472 <para>It's useful to remember that the <command role="hg-cmd">hg
473 revert</command> command is useful for changes that you have
474 not yet committed. Once you've committed a change, if you
475 decide it was a mistake, you can still do something about it,
476 though your options may be more limited.</para>
478 <para>For more information about the <command role="hg-cmd">hg
479 revert</command> command, and details about how to deal with
480 changes you have already committed, see chapter <xref
481 linkend="chap:undo"/>.</para>
483 </sect1>
484 </chapter>
486 <!--
487 local variables:
488 sgml-parent-document: ("00book.xml" "book" "chapter")
489 end:
490 -->