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