hgbook
diff en/ch05-daily.xml @ 561:21c62e09b99f
Typo and spelling corrections. Removed tex tags.
author | Ori Avtalion <ori@avtalion.name> |
---|---|
date | Thu Mar 05 21:52:23 2009 +0200 (2009-03-05) |
parents | f72b7e6cbe90 |
children | 8fcd44708f41 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/en/ch05-daily.xml Thu Mar 05 21:52:23 2009 +0200 1.3 @@ -0,0 +1,490 @@ 1.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.5 + 1.6 +<chapter id="chap:daily"> 1.7 + <title>Mercurial in daily use</title> 1.8 + 1.9 + <sect1> 1.10 + <title>Telling Mercurial which files to track</title> 1.11 + 1.12 + <para>Mercurial does not work with files in your repository unless 1.13 + you tell it to manage them. The <command role="hg-cmd">hg 1.14 + status</command> command will tell you which files Mercurial 1.15 + doesn't know about; it uses a 1.16 + <quote><literal>?</literal></quote> to display such 1.17 + files.</para> 1.18 + 1.19 + <para>To tell Mercurial to track a file, use the <command 1.20 + role="hg-cmd">hg add</command> command. Once you have added a 1.21 + file, the entry in the output of <command role="hg-cmd">hg 1.22 + status</command> for that file changes from 1.23 + <quote><literal>?</literal></quote> to 1.24 + <quote><literal>A</literal></quote>. <!-- 1.25 + &interaction.daily.files.add; --></para> 1.26 + 1.27 + <para>After you run a <command role="hg-cmd">hg commit</command>, 1.28 + the files that you added before the commit will no longer be 1.29 + listed in the output of <command role="hg-cmd">hg 1.30 + status</command>. The reason for this is that <command 1.31 + role="hg-cmd">hg status</command> only tells you about 1.32 + <quote>interesting</quote> files&emdash;those that you have 1.33 + modified or told Mercurial to do something with&emdash;by 1.34 + default. If you have a repository that contains thousands of 1.35 + files, you will rarely want to know about files that Mercurial 1.36 + is tracking, but that have not changed. (You can still get this 1.37 + information; we'll return to this later.)</para> 1.38 + 1.39 + <para>Once you add a file, Mercurial doesn't do anything with it 1.40 + immediately. Instead, it will take a snapshot of the file's 1.41 + state the next time you perform a commit. It will then continue 1.42 + to track the changes you make to the file every time you commit, 1.43 + until you remove the file.</para> 1.44 + 1.45 + <sect2> 1.46 + <title>Explicit versus implicit file naming</title> 1.47 + 1.48 + <para>A useful behaviour that Mercurial has is that if you pass 1.49 + the name of a directory to a command, every Mercurial command 1.50 + will treat this as <quote>I want to operate on every file in 1.51 + this directory and its subdirectories</quote>. <!-- 1.52 + &interaction.daily.files.add-dir; --> Notice in this example 1.53 + that Mercurial printed the names of the files it added, 1.54 + whereas it didn't do so when we added the file named 1.55 + <filename>a</filename> in the earlier example.</para> 1.56 + 1.57 + <para>What's going on is that in the former case, we explicitly 1.58 + named the file to add on the command line, so the assumption 1.59 + that Mercurial makes in such cases is that you know what you 1.60 + were doing, and it doesn't print any output.</para> 1.61 + 1.62 + <para>However, when we <emphasis>imply</emphasis> the names of 1.63 + files by giving the name of a directory, Mercurial takes the 1.64 + extra step of printing the name of each file that it does 1.65 + something with. This makes it more clear what is happening, 1.66 + and reduces the likelihood of a silent and nasty surprise. 1.67 + This behaviour is common to most Mercurial commands.</para> 1.68 + 1.69 + </sect2> 1.70 + <sect2> 1.71 + <title>Aside: Mercurial tracks files, not directories</title> 1.72 + 1.73 + <para>Mercurial does not track directory information. Instead, 1.74 + it tracks the path to a file. Before creating a file, it 1.75 + first creates any missing directory components of the path. 1.76 + After it deletes a file, it then deletes any empty directories 1.77 + that were in the deleted file's path. This sounds like a 1.78 + trivial distinction, but it has one minor practical 1.79 + consequence: it is not possible to represent a completely 1.80 + empty directory in Mercurial.</para> 1.81 + 1.82 + <para>Empty directories are rarely useful, and there are 1.83 + unintrusive workarounds that you can use to achieve an 1.84 + appropriate effect. The developers of Mercurial thus felt 1.85 + that the complexity that would be required to manage empty 1.86 + directories was not worth the limited benefit this feature 1.87 + would bring.</para> 1.88 + 1.89 + <para>If you need an empty directory in your repository, there 1.90 + are a few ways to achieve this. One is to create a directory, 1.91 + then <command role="hg-cmd">hg add</command> a 1.92 + <quote>hidden</quote> file to that directory. On Unix-like 1.93 + systems, any file name that begins with a period 1.94 + (<quote><literal>.</literal></quote>) is treated as hidden by 1.95 + most commands and GUI tools. This approach is illustrated 1.96 + below.</para> 1.97 + 1.98 +<!-- &interaction.daily.files.hidden; --> 1.99 + 1.100 + <para>Another way to tackle a need for an empty directory is to 1.101 + simply create one in your automated build scripts before they 1.102 + will need it.</para> 1.103 + 1.104 + </sect2> 1.105 + </sect1> 1.106 + <sect1> 1.107 + <title>How to stop tracking a file</title> 1.108 + 1.109 + <para>Once you decide that a file no longer belongs in your 1.110 + repository, use the <command role="hg-cmd">hg remove</command> 1.111 + command; this deletes the file, and tells Mercurial to stop 1.112 + tracking it. A removed file is represented in the output of 1.113 + <command role="hg-cmd">hg status</command> with a 1.114 + <quote><literal>R</literal></quote>. <!-- 1.115 + &interaction.daily.files.remove; --></para> 1.116 + 1.117 + <para>After you <command role="hg-cmd">hg remove</command> a file, 1.118 + Mercurial will no longer track changes to that file, even if you 1.119 + recreate a file with the same name in your working directory. 1.120 + If you do recreate a file with the same name and want Mercurial 1.121 + to track the new file, simply <command role="hg-cmd">hg 1.122 + add</command> it. Mercurial will know that the newly added 1.123 + file is not related to the old file of the same name.</para> 1.124 + 1.125 + <sect2> 1.126 + <title>Removing a file does not affect its history</title> 1.127 + 1.128 + <para>It is important to understand that removing a file has 1.129 + only two effects.</para> 1.130 + <itemizedlist> 1.131 + <listitem><para>It removes the current version of the file 1.132 + from the working directory.</para> 1.133 + </listitem> 1.134 + <listitem><para>It stops Mercurial from tracking changes to 1.135 + the file, from the time of the next commit.</para> 1.136 + </listitem></itemizedlist> 1.137 + <para>Removing a file <emphasis>does not</emphasis> in any way 1.138 + alter the <emphasis>history</emphasis> of the file.</para> 1.139 + 1.140 + <para>If you update the working directory to a changeset in 1.141 + which a file that you have removed was still tracked, it will 1.142 + reappear in the working directory, with the contents it had 1.143 + when you committed that changeset. If you then update the 1.144 + working directory to a later changeset, in which the file had 1.145 + been removed, Mercurial will once again remove the file from 1.146 + the working directory.</para> 1.147 + 1.148 + </sect2> 1.149 + <sect2> 1.150 + <title>Missing files</title> 1.151 + 1.152 + <para>Mercurial considers a file that you have deleted, but not 1.153 + used <command role="hg-cmd">hg remove</command> to delete, to 1.154 + be <emphasis>missing</emphasis>. A missing file is 1.155 + represented with <quote><literal>!</literal></quote> in the 1.156 + output of <command role="hg-cmd">hg status</command>. 1.157 + Mercurial commands will not generally do anything with missing 1.158 + files. <!-- &interaction.daily.files.missing; --></para> 1.159 + 1.160 + <para>If your repository contains a file that <command 1.161 + role="hg-cmd">hg status</command> reports as missing, and 1.162 + you want the file to stay gone, you can run <command 1.163 + role="hg-cmd">hg remove <option 1.164 + role="hg-opt-remove">--after</option></command> at any 1.165 + time later on, to tell Mercurial that you really did mean to 1.166 + remove the file. <!-- &interaction.daily.files.remove-after; 1.167 + --></para> 1.168 + 1.169 + <para>On the other hand, if you deleted the missing file by 1.170 + accident, give <command role="hg-cmd">hg revert</command> the 1.171 + name of the file to recover. It will reappear, in unmodified 1.172 + form.</para> 1.173 + 1.174 +<!-- &interaction.daily.files.recover-missing; --> 1.175 + 1.176 + </sect2> 1.177 + <sect2> 1.178 + <title>Aside: why tell Mercurial explicitly to remove a 1.179 + file?</title> 1.180 + 1.181 + <para>You might wonder why Mercurial requires you to explicitly 1.182 + tell it that you are deleting a file. Early during the 1.183 + development of Mercurial, it let you delete a file however you 1.184 + pleased; Mercurial would notice the absence of the file 1.185 + automatically when you next ran a <command role="hg-cmd">hg 1.186 + commit</command>, and stop tracking the file. In practice, 1.187 + this made it too easy to accidentally remove a file without 1.188 + noticing.</para> 1.189 + 1.190 + </sect2> 1.191 + <sect2> 1.192 + <title>Useful shorthand&emdash;adding and removing files in one 1.193 + step</title> 1.194 + 1.195 + <para>Mercurial offers a combination command, <command 1.196 + role="hg-cmd">hg addremove</command>, that adds untracked 1.197 + files and marks missing files as removed. <!-- 1.198 + &interaction.daily.files.addremove; --> The <command 1.199 + role="hg-cmd">hg commit</command> command also provides a 1.200 + <option role="hg-opt-commit">-A</option> option that performs 1.201 + this same add-and-remove, immediately followed by a commit. 1.202 + <!-- &interaction.daily.files.commit-addremove; --></para> 1.203 + 1.204 + </sect2> 1.205 + </sect1> 1.206 + <sect1> 1.207 + <title>Copying files</title> 1.208 + 1.209 + <para>Mercurial provides a <command role="hg-cmd">hg 1.210 + copy</command> command that lets you make a new copy of a 1.211 + file. When you copy a file using this command, Mercurial makes 1.212 + a record of the fact that the new file is a copy of the original 1.213 + file. It treats these copied files specially when you merge 1.214 + your work with someone else's.</para> 1.215 + 1.216 + <sect2> 1.217 + <title>The results of copying during a merge</title> 1.218 + 1.219 + <para>What happens during a merge is that changes 1.220 + <quote>follow</quote> a copy. To best illustrate what this 1.221 + means, let's create an example. We'll start with the usual 1.222 + tiny repository that contains a single file. <!-- 1.223 + &interaction.daily.copy.init; --> We need to do some work in 1.224 + parallel, so that we'll have something to merge. So let's 1.225 + clone our repository. <!-- &interaction.daily.copy.clone; --> 1.226 + Back in our initial repository, let's use the <command 1.227 + role="hg-cmd">hg copy</command> command to make a copy of 1.228 + the first file we created. <!-- &interaction.daily.copy.copy; 1.229 + --></para> 1.230 + 1.231 + <para>If we look at the output of the <command role="hg-cmd">hg 1.232 + status</command> command afterwards, the copied file looks 1.233 + just like a normal added file. <!-- 1.234 + &interaction.daily.copy.status; --> But if we pass the <option 1.235 + role="hg-opt-status">-C</option> option to <command 1.236 + role="hg-cmd">hg status</command>, it prints another line of 1.237 + output: this is the file that our newly-added file was copied 1.238 + <emphasis>from</emphasis>. <!-- 1.239 + &interaction.daily.copy.status-copy; --></para> 1.240 + 1.241 + <para>Now, back in the repository we cloned, let's make a change 1.242 + in parallel. We'll add a line of content to the original file 1.243 + that we created. <!-- &interaction.daily.copy.other; --> Now 1.244 + we have a modified <filename>file</filename> in this 1.245 + repository. When we pull the changes from the first 1.246 + repository, and merge the two heads, Mercurial will propagate 1.247 + the changes that we made locally to <filename>file</filename> 1.248 + into its copy, <filename>new-file</filename>. <!-- 1.249 + &interaction.daily.copy.merge; --></para> 1.250 + 1.251 + </sect2> 1.252 + <sect2 id="sec:daily:why-copy"> 1.253 + <title>Why should changes follow copies?</title> 1.254 + 1.255 + <para>This behaviour, of changes to a file propagating out to 1.256 + copies of the file, might seem esoteric, but in most cases 1.257 + it's highly desirable.</para> 1.258 + 1.259 + <para>First of all, remember that this propagation 1.260 + <emphasis>only</emphasis> happens when you merge. So if you 1.261 + <command role="hg-cmd">hg copy</command> a file, and 1.262 + subsequently modify the original file during the normal course 1.263 + of your work, nothing will happen.</para> 1.264 + 1.265 + <para>The second thing to know is that modifications will only 1.266 + propagate across a copy as long as the repository that you're 1.267 + pulling changes from <emphasis>doesn't know</emphasis> about 1.268 + the copy.</para> 1.269 + 1.270 + <para>The reason that Mercurial does this is as follows. Let's 1.271 + say I make an important bug fix in a source file, and commit 1.272 + my changes. Meanwhile, you've decided to <command 1.273 + role="hg-cmd">hg copy</command> the file in your repository, 1.274 + without knowing about the bug or having seen the fix, and you 1.275 + have started hacking on your copy of the file.</para> 1.276 + 1.277 + <para>If you pulled and merged my changes, and Mercurial 1.278 + <emphasis>didn't</emphasis> propagate changes across copies, 1.279 + your source file would now contain the bug, and unless you 1.280 + remembered to propagate the bug fix by hand, the bug would 1.281 + <emphasis>remain</emphasis> in your copy of the file.</para> 1.282 + 1.283 + <para>By automatically propagating the change that fixed the bug 1.284 + from the original file to the copy, Mercurial prevents this 1.285 + class of problem. To my knowledge, Mercurial is the 1.286 + <emphasis>only</emphasis> revision control system that 1.287 + propagates changes across copies like this.</para> 1.288 + 1.289 + <para>Once your change history has a record that the copy and 1.290 + subsequent merge occurred, there's usually no further need to 1.291 + propagate changes from the original file to the copied file, 1.292 + and that's why Mercurial only propagates changes across copies 1.293 + until this point, and no further.</para> 1.294 + 1.295 + </sect2> 1.296 + <sect2> 1.297 + <title>How to make changes <emphasis>not</emphasis> follow a 1.298 + copy</title> 1.299 + 1.300 + <para>If, for some reason, you decide that this business of 1.301 + automatically propagating changes across copies is not for 1.302 + you, simply use your system's normal file copy command (on 1.303 + Unix-like systems, that's <command>cp</command>) to make a 1.304 + copy of a file, then <command role="hg-cmd">hg add</command> 1.305 + the new copy by hand. Before you do so, though, please do 1.306 + reread section <xref linkend="sec:daily:why-copy"/>, and make 1.307 + an informed 1.308 + decision that this behaviour is not appropriate to your 1.309 + specific case.</para> 1.310 + 1.311 + </sect2> 1.312 + <sect2> 1.313 + <title>Behaviour of the <command role="hg-cmd">hg copy</command> 1.314 + command</title> 1.315 + 1.316 + <para>When you use the <command role="hg-cmd">hg copy</command> 1.317 + command, Mercurial makes a copy of each source file as it 1.318 + currently stands in the working directory. This means that if 1.319 + you make some modifications to a file, then <command 1.320 + role="hg-cmd">hg copy</command> it without first having 1.321 + committed those changes, the new copy will also contain the 1.322 + modifications you have made up until that point. (I find this 1.323 + behaviour a little counterintuitive, which is why I mention it 1.324 + here.)</para> 1.325 + 1.326 + <para>The <command role="hg-cmd">hg copy</command> command acts 1.327 + similarly to the Unix <command>cp</command> command (you can 1.328 + use the <command role="hg-cmd">hg cp</command> alias if you 1.329 + prefer). The last argument is the 1.330 + <emphasis>destination</emphasis>, and all prior arguments are 1.331 + <emphasis>sources</emphasis>. If you pass it a single file as 1.332 + the source, and the destination does not exist, it creates a 1.333 + new file with that name. <!-- &interaction.daily.copy.simple; 1.334 + --> If the destination is a directory, Mercurial copies its 1.335 + sources into that directory. <!-- 1.336 + &interaction.daily.copy.dir-dest; --> Copying a directory is 1.337 + recursive, and preserves the directory structure of the 1.338 + source. <!-- &interaction.daily.copy.dir-src; --> If the 1.339 + source and destination are both directories, the source tree 1.340 + is recreated in the destination directory. <!-- 1.341 + &interaction.daily.copy.dir-src-dest; --></para> 1.342 + 1.343 + <para>As with the <command role="hg-cmd">hg rename</command> 1.344 + command, if you copy a file manually and then want Mercurial 1.345 + to know that you've copied the file, simply use the <option 1.346 + role="hg-opt-copy">--after</option> option to <command 1.347 + role="hg-cmd">hg copy</command>. <!-- 1.348 + &interaction.daily.copy.after; --></para> 1.349 + 1.350 + </sect2> 1.351 + </sect1> 1.352 + <sect1> 1.353 + <title>Renaming files</title> 1.354 + 1.355 + <para>It's rather more common to need to rename a file than to 1.356 + make a copy of it. The reason I discussed the <command 1.357 + role="hg-cmd">hg copy</command> command before talking about 1.358 + renaming files is that Mercurial treats a rename in essentially 1.359 + the same way as a copy. Therefore, knowing what Mercurial does 1.360 + when you copy a file tells you what to expect when you rename a 1.361 + file.</para> 1.362 + 1.363 + <para>When you use the <command role="hg-cmd">hg rename</command> 1.364 + command, Mercurial makes a copy of each source file, then 1.365 + deletes it and marks the file as removed. <!-- 1.366 + &interaction.daily.rename.rename; --> The <command 1.367 + role="hg-cmd">hg status</command> command shows the newly 1.368 + copied file as added, and the copied-from file as removed. <!-- 1.369 + &interaction.daily.rename.status; --> As with the results of a 1.370 + <command role="hg-cmd">hg copy</command>, we must use the 1.371 + <option role="hg-opt-status">-C</option> option to <command 1.372 + role="hg-cmd">hg status</command> to see that the added file 1.373 + is really being tracked by Mercurial as a copy of the original, 1.374 + now removed, file. <!-- &interaction.daily.rename.status-copy; 1.375 + --></para> 1.376 + 1.377 + <para>As with <command role="hg-cmd">hg remove</command> and 1.378 + <command role="hg-cmd">hg copy</command>, you can tell Mercurial 1.379 + about a rename after the fact using the <option 1.380 + role="hg-opt-rename">--after</option> option. In most other 1.381 + respects, the behaviour of the <command role="hg-cmd">hg 1.382 + rename</command> command, and the options it accepts, are 1.383 + similar to the <command role="hg-cmd">hg copy</command> 1.384 + command.</para> 1.385 + 1.386 + <sect2> 1.387 + <title>Renaming files and merging changes</title> 1.388 + 1.389 + <para>Since Mercurial's rename is implemented as 1.390 + copy-and-remove, the same propagation of changes happens when 1.391 + you merge after a rename as after a copy.</para> 1.392 + 1.393 + <para>If I modify a file, and you rename it to a new name, and 1.394 + then we merge our respective changes, my modifications to the 1.395 + file under its original name will be propagated into the file 1.396 + under its new name. (This is something you might expect to 1.397 + <quote>simply work,</quote> but not all revision control 1.398 + systems actually do this.)</para> 1.399 + 1.400 + <para>Whereas having changes follow a copy is a feature where 1.401 + you can perhaps nod and say <quote>yes, that might be 1.402 + useful,</quote> it should be clear that having them follow a 1.403 + rename is definitely important. Without this facility, it 1.404 + would simply be too easy for changes to become orphaned when 1.405 + files are renamed.</para> 1.406 + 1.407 + </sect2> 1.408 + <sect2> 1.409 + <title>Divergent renames and merging</title> 1.410 + 1.411 + <para>The case of diverging names occurs when two developers 1.412 + start with a file&emdash;let's call it 1.413 + <filename>foo</filename>&emdash;in their respective 1.414 + repositories.</para> 1.415 + 1.416 + <para><!-- &interaction.rename.divergent.clone; --> Anne renames 1.417 + the file to <filename>bar</filename>. <!-- 1.418 + &interaction.rename.divergent.rename.anne; --> Meanwhile, Bob 1.419 + renames it to <filename>quux</filename>. <!-- 1.420 + &interaction.rename.divergent.rename.bob; --></para> 1.421 + 1.422 + <para>I like to think of this as a conflict because each 1.423 + developer has expressed different intentions about what the 1.424 + file ought to be named.</para> 1.425 + 1.426 + <para>What do you think should happen when they merge their 1.427 + work? Mercurial's actual behaviour is that it always preserves 1.428 + <emphasis>both</emphasis> names when it merges changesets that 1.429 + contain divergent renames. <!-- 1.430 + &interaction.rename.divergent.merge; --></para> 1.431 + 1.432 + <para>Notice that Mercurial does warn about the divergent 1.433 + renames, but it leaves it up to you to do something about the 1.434 + divergence after the merge.</para> 1.435 + 1.436 + </sect2> 1.437 + <sect2> 1.438 + <title>Convergent renames and merging</title> 1.439 + 1.440 + <para>Another kind of rename conflict occurs when two people 1.441 + choose to rename different <emphasis>source</emphasis> files 1.442 + to the same <emphasis>destination</emphasis>. In this case, 1.443 + Mercurial runs its normal merge machinery, and lets you guide 1.444 + it to a suitable resolution.</para> 1.445 + 1.446 + </sect2> 1.447 + <sect2> 1.448 + <title>Other name-related corner cases</title> 1.449 + 1.450 + <para>Mercurial has a longstanding bug in which it fails to 1.451 + handle a merge where one side has a file with a given name, 1.452 + while another has a directory with the same name. This is 1.453 + documented as <ulink role="hg-bug" 1.454 + url="http://www.selenic.com/mercurial/bts/issue29">issue 1.455 + 29</ulink>. <!-- &interaction.issue29.go; --></para> 1.456 + 1.457 + </sect2> 1.458 + </sect1> 1.459 + <sect1> 1.460 + <title>Recovering from mistakes</title> 1.461 + 1.462 + <para>Mercurial has some useful commands that will help you to 1.463 + recover from some common mistakes.</para> 1.464 + 1.465 + <para>The <command role="hg-cmd">hg revert</command> command lets 1.466 + you undo changes that you have made to your working directory. 1.467 + For example, if you <command role="hg-cmd">hg add</command> a 1.468 + file by accident, just run <command role="hg-cmd">hg 1.469 + revert</command> with the name of the file you added, and 1.470 + while the file won't be touched in any way, it won't be tracked 1.471 + for adding by Mercurial any longer, either. You can also use 1.472 + <command role="hg-cmd">hg revert</command> to get rid of 1.473 + erroneous changes to a file.</para> 1.474 + 1.475 + <para>It's useful to remember that the <command role="hg-cmd">hg 1.476 + revert</command> command is useful for changes that you have 1.477 + not yet committed. Once you've committed a change, if you 1.478 + decide it was a mistake, you can still do something about it, 1.479 + though your options may be more limited.</para> 1.480 + 1.481 + <para>For more information about the <command role="hg-cmd">hg 1.482 + revert</command> command, and details about how to deal with 1.483 + changes you have already committed, see chapter <xref 1.484 + linkend="chap:undo"/>.</para> 1.485 + 1.486 + </sect1> 1.487 +</chapter> 1.488 + 1.489 +<!-- 1.490 +local variables: 1.491 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.492 +end: 1.493 +-->