hgbook

view fr/ch05-daily.xml @ 977:719b03ea27c8

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