hgbook
annotate en/ch05-daily.xml @ 1114:527b86d55d4a
inotify: update installation information
inotify is shipped in Mercurial since 1.0, which greatly simplifies the installation process
inotify is shipped in Mercurial since 1.0, which greatly simplifies the installation process
author | Nicolas Dumazet <nicdumz.commits@gmail.com> |
---|---|
date | Sun Dec 13 16:35:56 2009 +0900 (2009-12-13) |
parents | 477d6a3e5023 |
children |
rev | line source |
---|---|
bos@559 | 1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
bos@559 | 2 |
bos@685 | 3 <chapter id="chap:daily"> |
bos@572 | 4 <?dbhtml filename="mercurial-in-daily-use.html"?> |
bos@559 | 5 <title>Mercurial in daily use</title> |
bos@559 | 6 |
bos@559 | 7 <sect1> |
bos@559 | 8 <title>Telling Mercurial which files to track</title> |
bos@559 | 9 |
bos@584 | 10 <para id="x_1a3">Mercurial does not work with files in your repository unless |
bos@559 | 11 you tell it to manage them. The <command role="hg-cmd">hg |
bos@559 | 12 status</command> command will tell you which files Mercurial |
bos@559 | 13 doesn't know about; it uses a |
bos@559 | 14 <quote><literal>?</literal></quote> to display such |
bos@559 | 15 files.</para> |
bos@559 | 16 |
bos@584 | 17 <para id="x_1a4">To tell Mercurial to track a file, use the <command |
bos@559 | 18 role="hg-cmd">hg add</command> command. Once you have added a |
bos@559 | 19 file, the entry in the output of <command role="hg-cmd">hg |
bos@559 | 20 status</command> for that file changes from |
bos@559 | 21 <quote><literal>?</literal></quote> to |
bos@567 | 22 <quote><literal>A</literal></quote>.</para> |
bos@567 | 23 |
bos@567 | 24 &interaction.daily.files.add; |
bos@559 | 25 |
bos@584 | 26 <para id="x_1a5">After you run a <command role="hg-cmd">hg commit</command>, |
bos@559 | 27 the files that you added before the commit will no longer be |
bos@559 | 28 listed in the output of <command role="hg-cmd">hg |
bos@674 | 29 status</command>. The reason for this is that by default, <command |
bos@559 | 30 role="hg-cmd">hg status</command> only tells you about |
bos@674 | 31 <quote>interesting</quote> files&emdash;those that you have (for |
bos@674 | 32 example) modified, removed, or renamed. If you have a repository |
bos@674 | 33 that contains thousands of files, you will rarely want to know |
bos@674 | 34 about files that Mercurial is tracking, but that have not |
bos@674 | 35 changed. (You can still get this information; we'll return to |
bos@674 | 36 this later.)</para> |
bos@559 | 37 |
bos@584 | 38 <para id="x_1a6">Once you add a file, Mercurial doesn't do anything with it |
bos@559 | 39 immediately. Instead, it will take a snapshot of the file's |
bos@559 | 40 state the next time you perform a commit. It will then continue |
bos@559 | 41 to track the changes you make to the file every time you commit, |
bos@559 | 42 until you remove the file.</para> |
bos@559 | 43 |
bos@559 | 44 <sect2> |
bos@559 | 45 <title>Explicit versus implicit file naming</title> |
bos@559 | 46 |
bos@672 | 47 <para id="x_1a7">A useful behavior that Mercurial has is that if you pass |
bos@559 | 48 the name of a directory to a command, every Mercurial command |
bos@559 | 49 will treat this as <quote>I want to operate on every file in |
bos@567 | 50 this directory and its subdirectories</quote>.</para> |
bos@567 | 51 |
bos@567 | 52 &interaction.daily.files.add-dir; |
bos@567 | 53 |
bos@674 | 54 <para id="x_1a8">Notice in this example that Mercurial printed |
bos@674 | 55 the names of the files it added, whereas it didn't do so when |
bos@674 | 56 we added the file named <filename>myfile.txt</filename> in the |
bos@674 | 57 earlier example.</para> |
bos@559 | 58 |
bos@584 | 59 <para id="x_1a9">What's going on is that in the former case, we explicitly |
bos@674 | 60 named the file to add on the command line. The assumption |
bos@674 | 61 that Mercurial makes in such cases is that we know what we |
bos@674 | 62 are doing, and it doesn't print any output.</para> |
bos@559 | 63 |
bos@584 | 64 <para id="x_1aa">However, when we <emphasis>imply</emphasis> the names of |
bos@559 | 65 files by giving the name of a directory, Mercurial takes the |
bos@559 | 66 extra step of printing the name of each file that it does |
bos@559 | 67 something with. This makes it more clear what is happening, |
bos@559 | 68 and reduces the likelihood of a silent and nasty surprise. |
bos@672 | 69 This behavior is common to most Mercurial commands.</para> |
bos@674 | 70 </sect2> |
bos@674 | 71 |
bos@672 | 72 <sect2> |
bos@672 | 73 <title>Mercurial tracks files, not directories</title> |
bos@559 | 74 |
bos@584 | 75 <para id="x_1ab">Mercurial does not track directory information. Instead, |
bos@559 | 76 it tracks the path to a file. Before creating a file, it |
bos@559 | 77 first creates any missing directory components of the path. |
bos@559 | 78 After it deletes a file, it then deletes any empty directories |
bos@559 | 79 that were in the deleted file's path. This sounds like a |
bos@559 | 80 trivial distinction, but it has one minor practical |
bos@559 | 81 consequence: it is not possible to represent a completely |
bos@559 | 82 empty directory in Mercurial.</para> |
bos@559 | 83 |
bos@584 | 84 <para id="x_1ac">Empty directories are rarely useful, and there are |
bos@559 | 85 unintrusive workarounds that you can use to achieve an |
bos@559 | 86 appropriate effect. The developers of Mercurial thus felt |
bos@559 | 87 that the complexity that would be required to manage empty |
bos@559 | 88 directories was not worth the limited benefit this feature |
bos@559 | 89 would bring.</para> |
bos@559 | 90 |
bos@584 | 91 <para id="x_1ad">If you need an empty directory in your repository, there |
bos@559 | 92 are a few ways to achieve this. One is to create a directory, |
bos@559 | 93 then <command role="hg-cmd">hg add</command> a |
bos@559 | 94 <quote>hidden</quote> file to that directory. On Unix-like |
bos@559 | 95 systems, any file name that begins with a period |
bos@559 | 96 (<quote><literal>.</literal></quote>) is treated as hidden by |
bos@559 | 97 most commands and GUI tools. This approach is illustrated |
bos@559 | 98 below.</para> |
bos@559 | 99 |
bos@567 | 100 &interaction.daily.files.hidden; |
bos@559 | 101 |
bos@584 | 102 <para id="x_1ae">Another way to tackle a need for an empty directory is to |
bos@559 | 103 simply create one in your automated build scripts before they |
bos@559 | 104 will need it.</para> |
bos@559 | 105 </sect2> |
bos@559 | 106 </sect1> |
bos@674 | 107 |
bos@559 | 108 <sect1> |
bos@559 | 109 <title>How to stop tracking a file</title> |
bos@559 | 110 |
bos@701 | 111 <para id="x_1af">Once you decide that a file no longer belongs in |
bos@701 | 112 your repository, use the <command role="hg-cmd">hg |
bos@701 | 113 remove</command> command. This deletes the file, and tells |
bos@701 | 114 Mercurial to stop tracking it (which will occur at the next |
bos@701 | 115 commit). A removed file is represented in the output of |
bos@559 | 116 <command role="hg-cmd">hg status</command> with a |
bos@567 | 117 <quote><literal>R</literal></quote>.</para> |
bos@567 | 118 |
bos@567 | 119 &interaction.daily.files.remove; |
bos@559 | 120 |
bos@584 | 121 <para id="x_1b0">After you <command role="hg-cmd">hg remove</command> a file, |
bos@559 | 122 Mercurial will no longer track changes to that file, even if you |
bos@559 | 123 recreate a file with the same name in your working directory. |
bos@559 | 124 If you do recreate a file with the same name and want Mercurial |
bos@559 | 125 to track the new file, simply <command role="hg-cmd">hg |
bos@559 | 126 add</command> it. Mercurial will know that the newly added |
bos@559 | 127 file is not related to the old file of the same name.</para> |
bos@559 | 128 |
bos@559 | 129 <sect2> |
bos@559 | 130 <title>Removing a file does not affect its history</title> |
bos@559 | 131 |
bos@584 | 132 <para id="x_1b1">It is important to understand that removing a file has |
bos@559 | 133 only two effects.</para> |
bos@559 | 134 <itemizedlist> |
bos@584 | 135 <listitem><para id="x_1b2">It removes the current version of the file |
bos@559 | 136 from the working directory.</para> |
bos@559 | 137 </listitem> |
bos@584 | 138 <listitem><para id="x_1b3">It stops Mercurial from tracking changes to |
bos@559 | 139 the file, from the time of the next commit.</para> |
bos@559 | 140 </listitem></itemizedlist> |
bos@584 | 141 <para id="x_1b4">Removing a file <emphasis>does not</emphasis> in any way |
bos@559 | 142 alter the <emphasis>history</emphasis> of the file.</para> |
bos@559 | 143 |
bos@674 | 144 <para id="x_1b5">If you update the working directory to a |
bos@674 | 145 changeset that was committed when it was still tracking a file |
bos@674 | 146 that you later removed, the file will reappear in the working |
bos@674 | 147 directory, with the contents it had when you committed that |
bos@674 | 148 changeset. If you then update the working directory to a |
bos@674 | 149 later changeset, in which the file had been removed, Mercurial |
bos@674 | 150 will once again remove the file from the working |
bos@674 | 151 directory.</para> |
bos@674 | 152 </sect2> |
bos@674 | 153 |
bos@559 | 154 <sect2> |
bos@559 | 155 <title>Missing files</title> |
bos@559 | 156 |
bos@584 | 157 <para id="x_1b6">Mercurial considers a file that you have deleted, but not |
bos@559 | 158 used <command role="hg-cmd">hg remove</command> to delete, to |
bos@559 | 159 be <emphasis>missing</emphasis>. A missing file is |
bos@559 | 160 represented with <quote><literal>!</literal></quote> in the |
bos@559 | 161 output of <command role="hg-cmd">hg status</command>. |
bos@559 | 162 Mercurial commands will not generally do anything with missing |
bos@567 | 163 files.</para> |
bos@567 | 164 |
bos@567 | 165 &interaction.daily.files.missing; |
bos@559 | 166 |
bos@584 | 167 <para id="x_1b7">If your repository contains a file that <command |
bos@559 | 168 role="hg-cmd">hg status</command> reports as missing, and |
bos@559 | 169 you want the file to stay gone, you can run <command |
bos@559 | 170 role="hg-cmd">hg remove <option |
bos@559 | 171 role="hg-opt-remove">--after</option></command> at any |
bos@559 | 172 time later on, to tell Mercurial that you really did mean to |
bos@567 | 173 remove the file.</para> |
bos@567 | 174 |
bos@567 | 175 &interaction.daily.files.remove-after; |
bos@559 | 176 |
bos@584 | 177 <para id="x_1b8">On the other hand, if you deleted the missing file by |
bos@559 | 178 accident, give <command role="hg-cmd">hg revert</command> the |
bos@559 | 179 name of the file to recover. It will reappear, in unmodified |
bos@559 | 180 form.</para> |
bos@559 | 181 |
bos@674 | 182 &interaction.daily.files.recover-missing; |
bos@674 | 183 </sect2> |
bos@674 | 184 |
bos@559 | 185 <sect2> |
bos@559 | 186 <title>Aside: why tell Mercurial explicitly to remove a |
bos@559 | 187 file?</title> |
bos@559 | 188 |
bos@584 | 189 <para id="x_1b9">You might wonder why Mercurial requires you to explicitly |
bos@559 | 190 tell it that you are deleting a file. Early during the |
bos@559 | 191 development of Mercurial, it let you delete a file however you |
bos@559 | 192 pleased; Mercurial would notice the absence of the file |
bos@559 | 193 automatically when you next ran a <command role="hg-cmd">hg |
bos@559 | 194 commit</command>, and stop tracking the file. In practice, |
bos@559 | 195 this made it too easy to accidentally remove a file without |
bos@559 | 196 noticing.</para> |
bos@674 | 197 </sect2> |
bos@674 | 198 |
bos@559 | 199 <sect2> |
bos@559 | 200 <title>Useful shorthand&emdash;adding and removing files in one |
bos@559 | 201 step</title> |
bos@559 | 202 |
bos@584 | 203 <para id="x_1ba">Mercurial offers a combination command, <command |
bos@559 | 204 role="hg-cmd">hg addremove</command>, that adds untracked |
bos@567 | 205 files and marks missing files as removed.</para> |
bos@567 | 206 |
bos@567 | 207 &interaction.daily.files.addremove; |
bos@567 | 208 |
bos@584 | 209 <para id="x_1bb">The <command role="hg-cmd">hg commit</command> command |
bos@567 | 210 also provides a <option role="hg-opt-commit">-A</option> |
bos@567 | 211 option that performs this same add-and-remove, immediately |
bos@567 | 212 followed by a commit.</para> |
bos@567 | 213 |
bos@567 | 214 &interaction.daily.files.commit-addremove; |
bos@559 | 215 </sect2> |
bos@559 | 216 </sect1> |
bos@674 | 217 |
bos@701 | 218 <sect1 id="chap:daily.copy"> |
bos@559 | 219 <title>Copying files</title> |
bos@559 | 220 |
bos@584 | 221 <para id="x_1bc">Mercurial provides a <command role="hg-cmd">hg |
bos@559 | 222 copy</command> command that lets you make a new copy of a |
bos@559 | 223 file. When you copy a file using this command, Mercurial makes |
bos@559 | 224 a record of the fact that the new file is a copy of the original |
bos@559 | 225 file. It treats these copied files specially when you merge |
bos@559 | 226 your work with someone else's.</para> |
bos@559 | 227 |
bos@559 | 228 <sect2> |
bos@559 | 229 <title>The results of copying during a merge</title> |
bos@559 | 230 |
bos@584 | 231 <para id="x_1bd">What happens during a merge is that changes |
bos@559 | 232 <quote>follow</quote> a copy. To best illustrate what this |
bos@559 | 233 means, let's create an example. We'll start with the usual |
bos@567 | 234 tiny repository that contains a single file.</para> |
bos@567 | 235 |
bos@567 | 236 &interaction.daily.copy.init; |
bos@567 | 237 |
bos@584 | 238 <para id="x_1be">We need to do some work in |
bos@559 | 239 parallel, so that we'll have something to merge. So let's |
bos@567 | 240 clone our repository.</para> |
bos@567 | 241 |
bos@567 | 242 &interaction.daily.copy.clone; |
bos@567 | 243 |
bos@584 | 244 <para id="x_1bf">Back in our initial repository, let's use the <command |
bos@559 | 245 role="hg-cmd">hg copy</command> command to make a copy of |
bos@567 | 246 the first file we created.</para> |
bos@567 | 247 |
bos@567 | 248 &interaction.daily.copy.copy; |
bos@559 | 249 |
bos@584 | 250 <para id="x_1c0">If we look at the output of the <command role="hg-cmd">hg |
bos@559 | 251 status</command> command afterwards, the copied file looks |
bos@567 | 252 just like a normal added file.</para> |
bos@567 | 253 |
bos@567 | 254 &interaction.daily.copy.status; |
bos@567 | 255 |
bos@584 | 256 <para id="x_1c1">But if we pass the <option |
bos@559 | 257 role="hg-opt-status">-C</option> option to <command |
bos@559 | 258 role="hg-cmd">hg status</command>, it prints another line of |
bos@559 | 259 output: this is the file that our newly-added file was copied |
bos@567 | 260 <emphasis>from</emphasis>.</para> |
bos@567 | 261 |
bos@567 | 262 &interaction.daily.copy.status-copy; |
bos@559 | 263 |
bos@584 | 264 <para id="x_1c2">Now, back in the repository we cloned, let's make a change |
bos@559 | 265 in parallel. We'll add a line of content to the original file |
bos@567 | 266 that we created.</para> |
bos@567 | 267 |
bos@567 | 268 &interaction.daily.copy.other; |
bos@567 | 269 |
bos@584 | 270 <para id="x_1c3">Now we have a modified <filename>file</filename> in this |
bos@559 | 271 repository. When we pull the changes from the first |
bos@559 | 272 repository, and merge the two heads, Mercurial will propagate |
bos@559 | 273 the changes that we made locally to <filename>file</filename> |
bos@567 | 274 into its copy, <filename>new-file</filename>.</para> |
bos@567 | 275 |
bos@567 | 276 &interaction.daily.copy.merge; |
bos@674 | 277 </sect2> |
bos@674 | 278 |
bos@559 | 279 <sect2 id="sec:daily:why-copy"> |
bos@559 | 280 <title>Why should changes follow copies?</title> |
bos@559 | 281 |
bos@674 | 282 <para id="x_1c4">This behavior&emdash;of changes to a file |
bos@674 | 283 propagating out to copies of the file&emdash;might seem |
bos@674 | 284 esoteric, but in most cases it's highly desirable.</para> |
bos@559 | 285 |
bos@584 | 286 <para id="x_1c5">First of all, remember that this propagation |
bos@559 | 287 <emphasis>only</emphasis> happens when you merge. So if you |
bos@559 | 288 <command role="hg-cmd">hg copy</command> a file, and |
bos@559 | 289 subsequently modify the original file during the normal course |
bos@559 | 290 of your work, nothing will happen.</para> |
bos@559 | 291 |
bos@584 | 292 <para id="x_1c6">The second thing to know is that modifications will only |
bos@674 | 293 propagate across a copy as long as the changeset that you're |
bos@674 | 294 merging changes from <emphasis>hasn't yet seen</emphasis> |
bos@559 | 295 the copy.</para> |
bos@559 | 296 |
bos@584 | 297 <para id="x_1c7">The reason that Mercurial does this is as follows. Let's |
bos@559 | 298 say I make an important bug fix in a source file, and commit |
bos@559 | 299 my changes. Meanwhile, you've decided to <command |
bos@559 | 300 role="hg-cmd">hg copy</command> the file in your repository, |
bos@559 | 301 without knowing about the bug or having seen the fix, and you |
bos@559 | 302 have started hacking on your copy of the file.</para> |
bos@559 | 303 |
bos@584 | 304 <para id="x_1c8">If you pulled and merged my changes, and Mercurial |
bos@559 | 305 <emphasis>didn't</emphasis> propagate changes across copies, |
bos@674 | 306 your new source file would now contain the bug, and unless you |
bos@674 | 307 knew to propagate the bug fix by hand, the bug would |
bos@559 | 308 <emphasis>remain</emphasis> in your copy of the file.</para> |
bos@559 | 309 |
bos@584 | 310 <para id="x_1c9">By automatically propagating the change that fixed the bug |
bos@559 | 311 from the original file to the copy, Mercurial prevents this |
bos@559 | 312 class of problem. To my knowledge, Mercurial is the |
bos@559 | 313 <emphasis>only</emphasis> revision control system that |
bos@559 | 314 propagates changes across copies like this.</para> |
bos@559 | 315 |
bos@584 | 316 <para id="x_1ca">Once your change history has a record that the copy and |
bos@559 | 317 subsequent merge occurred, there's usually no further need to |
bos@559 | 318 propagate changes from the original file to the copied file, |
bos@559 | 319 and that's why Mercurial only propagates changes across copies |
bos@674 | 320 at the first merge, and not afterwards.</para> |
bos@674 | 321 </sect2> |
bos@674 | 322 |
bos@559 | 323 <sect2> |
bos@559 | 324 <title>How to make changes <emphasis>not</emphasis> follow a |
bos@559 | 325 copy</title> |
bos@559 | 326 |
bos@584 | 327 <para id="x_1cb">If, for some reason, you decide that this business of |
bos@559 | 328 automatically propagating changes across copies is not for |
bos@559 | 329 you, simply use your system's normal file copy command (on |
bos@559 | 330 Unix-like systems, that's <command>cp</command>) to make a |
bos@559 | 331 copy of a file, then <command role="hg-cmd">hg add</command> |
bos@559 | 332 the new copy by hand. Before you do so, though, please do |
bos@592 | 333 reread <xref linkend="sec:daily:why-copy"/>, and make |
bos@559 | 334 an informed |
bos@672 | 335 decision that this behavior is not appropriate to your |
bos@559 | 336 specific case.</para> |
bos@559 | 337 |
bos@559 | 338 </sect2> |
bos@559 | 339 <sect2> |
bos@674 | 340 <title>Behavior of the <command role="hg-cmd">hg copy</command> |
bos@559 | 341 command</title> |
bos@559 | 342 |
bos@584 | 343 <para id="x_1cc">When you use the <command role="hg-cmd">hg copy</command> |
bos@559 | 344 command, Mercurial makes a copy of each source file as it |
bos@559 | 345 currently stands in the working directory. This means that if |
bos@559 | 346 you make some modifications to a file, then <command |
bos@559 | 347 role="hg-cmd">hg copy</command> it without first having |
bos@559 | 348 committed those changes, the new copy will also contain the |
bos@559 | 349 modifications you have made up until that point. (I find this |
bos@672 | 350 behavior a little counterintuitive, which is why I mention it |
bos@559 | 351 here.)</para> |
bos@559 | 352 |
bos@674 | 353 <para id="x_1cd">The <command role="hg-cmd">hg copy</command> |
bos@674 | 354 command acts similarly to the Unix <command>cp</command> |
bos@674 | 355 command (you can use the <command role="hg-cmd">hg |
bos@674 | 356 cp</command> alias if you prefer). We must supply two or |
bos@674 | 357 more arguments, of which the last is treated as the |
bos@674 | 358 <emphasis>destination</emphasis>, and all others are |
bos@674 | 359 <emphasis>sources</emphasis>.</para> |
bos@674 | 360 |
bos@676 | 361 <para id="x_685">If you pass <command role="hg-cmd">hg copy</command> a |
bos@674 | 362 single file as the source, and the destination does not exist, |
bos@674 | 363 it creates a new file with that name.</para> |
bos@567 | 364 |
bos@567 | 365 &interaction.daily.copy.simple; |
bos@567 | 366 |
bos@584 | 367 <para id="x_1ce">If the destination is a directory, Mercurial copies its |
bos@567 | 368 sources into that directory.</para> |
bos@567 | 369 |
bos@567 | 370 &interaction.daily.copy.dir-dest; |
bos@567 | 371 |
bos@584 | 372 <para id="x_1cf">Copying a directory is |
bos@559 | 373 recursive, and preserves the directory structure of the |
bos@567 | 374 source.</para> |
bos@567 | 375 |
bos@567 | 376 &interaction.daily.copy.dir-src; |
bos@567 | 377 |
bos@584 | 378 <para id="x_1d0">If the source and destination are both directories, the |
bos@567 | 379 source tree is recreated in the destination directory.</para> |
bos@567 | 380 |
bos@567 | 381 &interaction.daily.copy.dir-src-dest; |
bos@559 | 382 |
bos@674 | 383 <para id="x_1d1">As with the <command role="hg-cmd">hg remove</command> |
bos@559 | 384 command, if you copy a file manually and then want Mercurial |
bos@559 | 385 to know that you've copied the file, simply use the <option |
bos@559 | 386 role="hg-opt-copy">--after</option> option to <command |
bos@567 | 387 role="hg-cmd">hg copy</command>.</para> |
bos@567 | 388 |
bos@567 | 389 &interaction.daily.copy.after; |
bos@559 | 390 </sect2> |
bos@559 | 391 </sect1> |
bos@674 | 392 |
bos@559 | 393 <sect1> |
bos@559 | 394 <title>Renaming files</title> |
bos@559 | 395 |
bos@584 | 396 <para id="x_1d2">It's rather more common to need to rename a file than to |
bos@559 | 397 make a copy of it. The reason I discussed the <command |
bos@559 | 398 role="hg-cmd">hg copy</command> command before talking about |
bos@559 | 399 renaming files is that Mercurial treats a rename in essentially |
bos@559 | 400 the same way as a copy. Therefore, knowing what Mercurial does |
bos@559 | 401 when you copy a file tells you what to expect when you rename a |
bos@559 | 402 file.</para> |
bos@559 | 403 |
bos@584 | 404 <para id="x_1d3">When you use the <command role="hg-cmd">hg rename</command> |
bos@559 | 405 command, Mercurial makes a copy of each source file, then |
bos@567 | 406 deletes it and marks the file as removed.</para> |
bos@567 | 407 |
bos@567 | 408 &interaction.daily.rename.rename; |
bos@567 | 409 |
bos@584 | 410 <para id="x_1d4">The <command role="hg-cmd">hg status</command> command shows |
bos@567 | 411 the newly copied file as added, and the copied-from file as |
bos@567 | 412 removed.</para> |
bos@567 | 413 |
bos@567 | 414 &interaction.daily.rename.status; |
bos@567 | 415 |
bos@584 | 416 <para id="x_1d5">As with the results of a <command role="hg-cmd">hg |
bos@567 | 417 copy</command>, we must use the <option |
bos@567 | 418 role="hg-opt-status">-C</option> option to <command |
bos@559 | 419 role="hg-cmd">hg status</command> to see that the added file |
bos@559 | 420 is really being tracked by Mercurial as a copy of the original, |
bos@567 | 421 now removed, file.</para> |
bos@567 | 422 |
bos@567 | 423 &interaction.daily.rename.status-copy; |
bos@559 | 424 |
bos@584 | 425 <para id="x_1d6">As with <command role="hg-cmd">hg remove</command> and |
bos@559 | 426 <command role="hg-cmd">hg copy</command>, you can tell Mercurial |
bos@559 | 427 about a rename after the fact using the <option |
bos@559 | 428 role="hg-opt-rename">--after</option> option. In most other |
bos@672 | 429 respects, the behavior of the <command role="hg-cmd">hg |
bos@559 | 430 rename</command> command, and the options it accepts, are |
bos@559 | 431 similar to the <command role="hg-cmd">hg copy</command> |
bos@559 | 432 command.</para> |
bos@559 | 433 |
bos@676 | 434 <para id="x_686">If you're familiar with the Unix command line, you'll be |
bos@674 | 435 glad to know that <command role="hg-cmd">hg rename</command> |
bos@674 | 436 command can be invoked as <command role="hg-cmd">hg |
bos@674 | 437 mv</command>.</para> |
bos@674 | 438 |
bos@559 | 439 <sect2> |
bos@559 | 440 <title>Renaming files and merging changes</title> |
bos@559 | 441 |
bos@584 | 442 <para id="x_1d7">Since Mercurial's rename is implemented as |
bos@559 | 443 copy-and-remove, the same propagation of changes happens when |
bos@559 | 444 you merge after a rename as after a copy.</para> |
bos@559 | 445 |
bos@584 | 446 <para id="x_1d8">If I modify a file, and you rename it to a new name, and |
bos@559 | 447 then we merge our respective changes, my modifications to the |
bos@559 | 448 file under its original name will be propagated into the file |
bos@559 | 449 under its new name. (This is something you might expect to |
bos@559 | 450 <quote>simply work,</quote> but not all revision control |
bos@559 | 451 systems actually do this.)</para> |
bos@559 | 452 |
bos@584 | 453 <para id="x_1d9">Whereas having changes follow a copy is a feature where |
bos@559 | 454 you can perhaps nod and say <quote>yes, that might be |
bos@559 | 455 useful,</quote> it should be clear that having them follow a |
bos@559 | 456 rename is definitely important. Without this facility, it |
bos@559 | 457 would simply be too easy for changes to become orphaned when |
bos@559 | 458 files are renamed.</para> |
bos@674 | 459 </sect2> |
bos@674 | 460 |
bos@559 | 461 <sect2> |
bos@559 | 462 <title>Divergent renames and merging</title> |
bos@559 | 463 |
bos@584 | 464 <para id="x_1da">The case of diverging names occurs when two developers |
bos@559 | 465 start with a file&emdash;let's call it |
bos@559 | 466 <filename>foo</filename>&emdash;in their respective |
bos@559 | 467 repositories.</para> |
bos@559 | 468 |
bos@567 | 469 &interaction.rename.divergent.clone; |
bos@567 | 470 |
bos@584 | 471 <para id="x_1db">Anne renames the file to <filename>bar</filename>.</para> |
bos@567 | 472 |
bos@567 | 473 &interaction.rename.divergent.rename.anne; |
bos@567 | 474 |
bos@584 | 475 <para id="x_1dc">Meanwhile, Bob renames it to |
bos@674 | 476 <filename>quux</filename>. (Remember that <command |
bos@674 | 477 role="hg-cmd">hg mv</command> is an alias for <command |
bos@674 | 478 role="hg-cmd">hg rename</command>.)</para> |
bos@567 | 479 |
bos@567 | 480 &interaction.rename.divergent.rename.bob; |
bos@559 | 481 |
bos@584 | 482 <para id="x_1dd">I like to think of this as a conflict because each |
bos@559 | 483 developer has expressed different intentions about what the |
bos@559 | 484 file ought to be named.</para> |
bos@559 | 485 |
bos@584 | 486 <para id="x_1de">What do you think should happen when they merge their |
bos@672 | 487 work? Mercurial's actual behavior is that it always preserves |
bos@559 | 488 <emphasis>both</emphasis> names when it merges changesets that |
bos@567 | 489 contain divergent renames.</para> |
bos@567 | 490 |
bos@567 | 491 &interaction.rename.divergent.merge; |
bos@559 | 492 |
bos@674 | 493 <para id="x_1df">Notice that while Mercurial warns about the divergent |
bos@674 | 494 renames, it leaves it up to you to do something about the |
bos@559 | 495 divergence after the merge.</para> |
bos@674 | 496 </sect2> |
bos@674 | 497 |
bos@559 | 498 <sect2> |
bos@559 | 499 <title>Convergent renames and merging</title> |
bos@559 | 500 |
bos@584 | 501 <para id="x_1e0">Another kind of rename conflict occurs when two people |
bos@559 | 502 choose to rename different <emphasis>source</emphasis> files |
bos@559 | 503 to the same <emphasis>destination</emphasis>. In this case, |
bos@559 | 504 Mercurial runs its normal merge machinery, and lets you guide |
bos@559 | 505 it to a suitable resolution.</para> |
bos@674 | 506 </sect2> |
bos@674 | 507 |
bos@559 | 508 <sect2> |
bos@559 | 509 <title>Other name-related corner cases</title> |
bos@559 | 510 |
bos@584 | 511 <para id="x_1e1">Mercurial has a longstanding bug in which it fails to |
bos@559 | 512 handle a merge where one side has a file with a given name, |
bos@559 | 513 while another has a directory with the same name. This is |
bos@559 | 514 documented as <ulink role="hg-bug" |
bos@559 | 515 url="http://www.selenic.com/mercurial/bts/issue29">issue |
bos@567 | 516 29</ulink>.</para> |
bos@567 | 517 |
bos@567 | 518 &interaction.issue29.go; |
bos@559 | 519 |
bos@559 | 520 </sect2> |
bos@559 | 521 </sect1> |
bos@674 | 522 |
bos@559 | 523 <sect1> |
bos@559 | 524 <title>Recovering from mistakes</title> |
bos@559 | 525 |
bos@584 | 526 <para id="x_1e2">Mercurial has some useful commands that will help you to |
bos@559 | 527 recover from some common mistakes.</para> |
bos@559 | 528 |
bos@584 | 529 <para id="x_1e3">The <command role="hg-cmd">hg revert</command> command lets |
bos@559 | 530 you undo changes that you have made to your working directory. |
bos@559 | 531 For example, if you <command role="hg-cmd">hg add</command> a |
bos@559 | 532 file by accident, just run <command role="hg-cmd">hg |
bos@559 | 533 revert</command> with the name of the file you added, and |
bos@559 | 534 while the file won't be touched in any way, it won't be tracked |
bos@559 | 535 for adding by Mercurial any longer, either. You can also use |
bos@559 | 536 <command role="hg-cmd">hg revert</command> to get rid of |
bos@559 | 537 erroneous changes to a file.</para> |
bos@559 | 538 |
bos@701 | 539 <para id="x_1e4">It is helpful to remember that the <command |
bos@701 | 540 role="hg-cmd">hg revert</command> command is useful for |
bos@701 | 541 changes that you have not yet committed. Once you've committed |
bos@701 | 542 a change, if you decide it was a mistake, you can still do |
bos@701 | 543 something about it, though your options may be more |
bos@701 | 544 limited.</para> |
bos@559 | 545 |
bos@592 | 546 <para id="x_1e5">For more information about the <command |
bos@592 | 547 role="hg-cmd">hg revert</command> command, and details about |
bos@592 | 548 how to deal with changes you have already committed, see <xref |
bos@559 | 549 linkend="chap:undo"/>.</para> |
bos@674 | 550 </sect1> |
bos@674 | 551 |
bos@674 | 552 <sect1> |
bos@674 | 553 <title>Dealing with tricky merges</title> |
bos@674 | 554 |
bos@676 | 555 <para id="x_687">In a complicated or large project, it's not unusual for a |
bos@674 | 556 merge of two changesets to result in some headaches. Suppose |
bos@674 | 557 there's a big source file that's been extensively edited by each |
bos@674 | 558 side of a merge: this is almost inevitably going to result in |
bos@674 | 559 conflicts, some of which can take a few tries to sort |
bos@674 | 560 out.</para> |
bos@674 | 561 |
bos@676 | 562 <para id="x_688">Let's develop a simple case of this and see how to deal with |
bos@674 | 563 it. We'll start off with a repository containing one file, and |
bos@674 | 564 clone it twice.</para> |
bos@674 | 565 |
bos@674 | 566 &interaction.ch04-resolve.init; |
bos@674 | 567 |
bos@676 | 568 <para id="x_689">In one clone, we'll modify the file in one way.</para> |
bos@674 | 569 |
bos@674 | 570 &interaction.ch04-resolve.left; |
bos@674 | 571 |
bos@676 | 572 <para id="x_68a">In another, we'll modify the file differently.</para> |
bos@674 | 573 |
bos@674 | 574 &interaction.ch04-resolve.right; |
bos@674 | 575 |
bos@676 | 576 <para id="x_68b">Next, we'll pull each set of changes into our original |
bos@674 | 577 repo.</para> |
bos@674 | 578 |
bos@674 | 579 &interaction.ch04-resolve.pull; |
bos@674 | 580 |
bos@676 | 581 <para id="x_68c">We expect our repository to now contain two heads.</para> |
bos@674 | 582 |
bos@674 | 583 &interaction.ch04-resolve.heads; |
bos@674 | 584 |
bos@676 | 585 <para id="x_68d">Normally, if we run <command role="hg-cmd">hg |
bos@674 | 586 merge</command> at this point, it will drop us into a GUI that |
bos@674 | 587 will let us manually resolve the conflicting edits to |
bos@674 | 588 <filename>myfile.txt</filename>. However, to simplify things |
bos@674 | 589 for presentation here, we'd like the merge to fail immediately |
bos@674 | 590 instead. Here's one way we can do so.</para> |
bos@674 | 591 |
bos@674 | 592 &interaction.ch04-resolve.export; |
bos@674 | 593 |
bos@676 | 594 <para id="x_68e">We've told Mercurial's merge machinery to run the command |
bos@674 | 595 <command>false</command> (which, as we desire, fails |
bos@674 | 596 immediately) if it detects a merge that it can't sort out |
bos@674 | 597 automatically.</para> |
bos@674 | 598 |
bos@676 | 599 <para id="x_68f">If we now fire up <command role="hg-cmd">hg |
bos@674 | 600 merge</command>, it should grind to a halt and report a |
bos@674 | 601 failure.</para> |
bos@674 | 602 |
bos@674 | 603 &interaction.ch04-resolve.merge; |
bos@674 | 604 |
bos@676 | 605 <para id="x_690">Even if we don't notice that the merge failed, Mercurial |
bos@674 | 606 will prevent us from accidentally committing the result of a |
bos@674 | 607 failed merge.</para> |
bos@674 | 608 |
bos@674 | 609 &interaction.ch04-resolve.cifail; |
bos@674 | 610 |
bos@676 | 611 <para id="x_691">When <command role="hg-cmd">hg commit</command> fails in |
bos@674 | 612 this case, it suggests that we use the unfamiliar <command |
bos@674 | 613 role="hg-cmd">hg resolve</command> command. As usual, |
bos@674 | 614 <command role="hg-cmd">hg help resolve</command> will print a |
bos@674 | 615 helpful synopsis.</para> |
bos@674 | 616 |
bos@674 | 617 <sect2> |
bos@674 | 618 <title>File resolution states</title> |
bos@674 | 619 |
bos@676 | 620 <para id="x_692">When a merge occurs, most files will usually remain |
bos@674 | 621 unmodified. For each file where Mercurial has to do |
bos@674 | 622 something, it tracks the state of the file.</para> |
bos@674 | 623 |
bos@674 | 624 <itemizedlist> |
bos@674 | 625 <listitem> |
bos@676 | 626 <para id="x_693">A <emphasis>resolved</emphasis> file has been |
bos@674 | 627 successfully merged, either automatically by Mercurial or |
bos@674 | 628 manually with human intervention.</para> |
bos@674 | 629 </listitem> |
bos@674 | 630 <listitem> |
bos@676 | 631 <para id="x_694">An <emphasis>unresolved</emphasis> file was not merged |
bos@674 | 632 successfully, and needs more attention.</para> |
bos@674 | 633 </listitem> |
bos@674 | 634 </itemizedlist> |
bos@674 | 635 |
bos@676 | 636 <para id="x_695">If Mercurial sees <emphasis>any</emphasis> file in the |
bos@674 | 637 unresolved state after a merge, it considers the merge to have |
bos@674 | 638 failed. Fortunately, we do not need to restart the entire |
bos@674 | 639 merge from scratch.</para> |
bos@674 | 640 |
bos@676 | 641 <para id="x_696">The <option role="hg-opt-resolve">--list</option> or |
bos@674 | 642 <option role="hg-opt-resolve">-l</option> option to <command |
bos@674 | 643 role="hg-cmd">hg resolve</command> prints out the state of |
bos@674 | 644 each merged file.</para> |
bos@674 | 645 |
bos@674 | 646 &interaction.ch04-resolve.list; |
bos@674 | 647 |
bos@676 | 648 <para id="x_697">In the output from <command role="hg-cmd">hg |
bos@674 | 649 resolve</command>, a resolved file is marked with |
bos@674 | 650 <literal>R</literal>, while an unresolved file is marked with |
bos@674 | 651 <literal>U</literal>. If any files are listed with |
bos@674 | 652 <literal>U</literal>, we know that an attempt to commit the |
bos@674 | 653 results of the merge will fail.</para> |
bos@674 | 654 </sect2> |
bos@674 | 655 |
bos@674 | 656 <sect2> |
bos@674 | 657 <title>Resolving a file merge</title> |
bos@674 | 658 |
bos@676 | 659 <para id="x_698">We have several options to move a file from the unresolved |
bos@674 | 660 into the resolved state. By far the most common is to rerun |
bos@674 | 661 <command role="hg-cmd">hg resolve</command>. If we pass the |
bos@674 | 662 names of individual files or directories, it will retry the |
bos@674 | 663 merges of any unresolved files present in those locations. We |
bos@674 | 664 can also pass the <option role="hg-opt-resolve">--all</option> |
bos@674 | 665 or <option role="hg-opt-resolve">-a</option> option, which |
bos@674 | 666 will retry the merges of <emphasis>all</emphasis> unresolved |
bos@674 | 667 files.</para> |
bos@674 | 668 |
bos@676 | 669 <para id="x_699">Mercurial also lets us modify the resolution state of a |
bos@674 | 670 file directly. We can manually mark a file as resolved using |
bos@674 | 671 the <option role="hg-opt-resolve">--mark</option> option, or |
bos@674 | 672 as unresolved using the <option |
bos@674 | 673 role="hg-opt-resolve">--unmark</option> option. This allows |
bos@674 | 674 us to clean up a particularly messy merge by hand, and to keep |
bos@674 | 675 track of our progress with each file as we go.</para> |
bos@674 | 676 </sect2> |
bos@559 | 677 </sect1> |
bos@683 | 678 |
bos@683 | 679 <sect1> |
bos@683 | 680 <title>More useful diffs</title> |
bos@683 | 681 |
bos@684 | 682 <para id="x_6c7">The default output of the <command role="hg-cmd">hg |
bos@683 | 683 diff</command> command is backwards compatible with the |
bos@683 | 684 regular <command>diff</command> command, but this has some |
bos@683 | 685 drawbacks.</para> |
bos@683 | 686 |
bos@684 | 687 <para id="x_6c8">Consider the case where we use <command role="hg-cmd">hg |
bos@683 | 688 rename</command> to rename a file.</para> |
bos@683 | 689 |
bos@683 | 690 &interaction.ch04-diff.rename.basic; |
bos@683 | 691 |
bos@684 | 692 <para id="x_6c9">The output of <command role="hg-cmd">hg diff</command> above |
bos@683 | 693 obscures the fact that we simply renamed a file. The <command |
bos@683 | 694 role="hg-cmd">hg diff</command> command accepts an option, |
bos@683 | 695 <option>--git</option> or <option>-g</option>, to use a newer |
bos@683 | 696 diff format that displays such information in a more readable |
bos@683 | 697 form.</para> |
bos@683 | 698 |
bos@683 | 699 &interaction.ch04-diff.rename.git; |
bos@683 | 700 |
bos@684 | 701 <para id="x_6ca">This option also helps with a case that can otherwise be |
bos@683 | 702 confusing: a file that appears to be modified according to |
bos@683 | 703 <command role="hg-cmd">hg status</command>, but for which |
bos@683 | 704 <command role="hg-cmd">hg diff</command> prints nothing. This |
bos@683 | 705 situation can arise if we change the file's execute |
bos@683 | 706 permissions.</para> |
bos@683 | 707 |
bos@683 | 708 &interaction.ch04-diff.chmod; |
bos@683 | 709 |
bos@684 | 710 <para id="x_6cb">The normal <command>diff</command> command pays no attention |
bos@683 | 711 to file permissions, which is why <command role="hg-cmd">hg |
bos@683 | 712 diff</command> prints nothing by default. If we supply it |
bos@683 | 713 with the <option>-g</option> option, it tells us what really |
bos@683 | 714 happened.</para> |
bos@683 | 715 |
bos@683 | 716 &interaction.ch04-diff.chmod.git; |
bos@683 | 717 </sect1> |
bos@683 | 718 |
bos@683 | 719 <sect1> |
bos@683 | 720 <title>Which files to manage, and which to avoid</title> |
bos@683 | 721 |
bos@684 | 722 <para id="x_6cc">Revision control systems are generally best at managing text |
bos@683 | 723 files that are written by humans, such as source code, where the |
bos@683 | 724 files do not change much from one revision to the next. Some |
bos@683 | 725 centralized revision control systems can also deal tolerably |
bos@683 | 726 well with binary files, such as bitmap images.</para> |
bos@683 | 727 |
bos@684 | 728 <para id="x_6cd">For instance, a game development team will typically manage |
bos@683 | 729 both its source code and all of its binary assets (e.g. geometry |
bos@683 | 730 data, textures, map layouts) in a revision control |
bos@683 | 731 system.</para> |
bos@683 | 732 |
bos@684 | 733 <para id="x_6ce">Because it is usually impossible to merge two conflicting |
bos@683 | 734 modifications to a binary file, centralized systems often |
bos@683 | 735 provide a file locking mechanism that allow a user to say |
bos@683 | 736 <quote>I am the only person who can edit this |
bos@683 | 737 file</quote>.</para> |
bos@683 | 738 |
bos@684 | 739 <para id="x_6cf">Compared to a centralized system, a distributed revision |
bos@683 | 740 control system changes some of the factors that guide decisions |
bos@683 | 741 over which files to manage and how.</para> |
bos@683 | 742 |
bos@684 | 743 <para id="x_6d0">For instance, a distributed revision control system cannot, |
bos@683 | 744 by its nature, offer a file locking facility. There is thus no |
bos@683 | 745 built-in mechanism to prevent two people from making conflicting |
bos@683 | 746 changes to a binary file. If you have a team where several |
bos@683 | 747 people may be editing binary files frequently, it may not be a |
bos@683 | 748 good idea to use Mercurial&emdash;or any other distributed |
bos@683 | 749 revision control system&emdash;to manage those files.</para> |
bos@683 | 750 |
bos@684 | 751 <para id="x_6d1">When storing modifications to a file, Mercurial usually |
bos@683 | 752 saves only the differences between the previous and current |
bos@683 | 753 versions of the file. For most text files, this is extremely |
bos@683 | 754 efficient. However, some files (particularly binary files) are |
bos@683 | 755 laid out in such a way that even a small change to a file's |
bos@683 | 756 logical content results in many or most of the bytes inside the |
bos@683 | 757 file changing. For instance, compressed files are particularly |
bos@683 | 758 susceptible to this. If the differences between each successive |
bos@683 | 759 version of a file are always large, Mercurial will not be able |
bos@683 | 760 to store the file's revision history very efficiently. This can |
bos@683 | 761 affect both local storage needs and the amount of time it takes |
bos@683 | 762 to clone a repository.</para> |
bos@683 | 763 |
bos@684 | 764 <para id="x_6d2">To get an idea of how this could affect you in practice, |
bos@683 | 765 suppose you want to use Mercurial to manage an OpenOffice |
bos@683 | 766 document. OpenOffice stores documents on disk as compressed zip |
bos@683 | 767 files. Edit even a single letter of your document in OpenOffice, |
bos@683 | 768 and almost every byte in the entire file will change when you |
bos@683 | 769 save it. Now suppose that file is 2MB in size. Because most of |
bos@683 | 770 the file changes every time you save, Mercurial will have to |
bos@683 | 771 store all 2MB of the file every time you commit, even though |
bos@683 | 772 from your perspective, perhaps only a few words are changing |
bos@683 | 773 each time. A single frequently-edited file that is not friendly |
bos@683 | 774 to Mercurial's storage assumptions can easily have an outsized |
bos@683 | 775 effect on the size of the repository.</para> |
bos@683 | 776 |
bos@684 | 777 <para id="x_6d3">Even worse, if both you and someone else edit the OpenOffice |
bos@683 | 778 document you're working on, there is no useful way to merge your |
bos@683 | 779 work. In fact, there isn't even a good way to tell what the |
bos@683 | 780 differences are between your respective changes.</para> |
bos@683 | 781 |
bos@684 | 782 <para id="x_6d4">There are thus a few clear recommendations about specific |
bos@683 | 783 kinds of files to be very careful with.</para> |
bos@683 | 784 |
bos@683 | 785 <itemizedlist> |
bos@683 | 786 <listitem> |
bos@684 | 787 <para id="x_6d5">Files that are very large and incompressible, e.g. ISO |
bos@683 | 788 CD-ROM images, will by virtue of sheer size make clones over |
bos@683 | 789 a network very slow.</para> |
bos@683 | 790 </listitem> |
bos@683 | 791 <listitem> |
bos@684 | 792 <para id="x_6d6">Files that change a lot from one revision to the next |
bos@683 | 793 may be expensive to store if you edit them frequently, and |
bos@683 | 794 conflicts due to concurrent edits may be difficult to |
bos@683 | 795 resolve.</para> |
bos@683 | 796 </listitem> |
bos@683 | 797 </itemizedlist> |
bos@683 | 798 </sect1> |
bos@683 | 799 |
bos@683 | 800 <sect1> |
bos@683 | 801 <title>Backups and mirroring</title> |
bos@683 | 802 |
bos@684 | 803 <para id="x_6d7">Since Mercurial maintains a complete copy of history in each |
bos@683 | 804 clone, everyone who uses Mercurial to collaborate on a project |
bos@683 | 805 can potentially act as a source of backups in the event of a |
bos@683 | 806 catastrophe. If a central repository becomes unavailable, you |
bos@683 | 807 can construct a replacement simply by cloning a copy of the |
bos@683 | 808 repository from one contributor, and pulling any changes they |
bos@683 | 809 may not have seen from others.</para> |
bos@683 | 810 |
bos@684 | 811 <para id="x_6d8">It is simple to use Mercurial to perform off-site backups |
bos@683 | 812 and remote mirrors. Set up a periodic job (e.g. via the |
bos@683 | 813 <command>cron</command> command) on a remote server to pull |
bos@683 | 814 changes from your master repositories every hour. This will |
bos@683 | 815 only be tricky in the unlikely case that the number of master |
bos@683 | 816 repositories you maintain changes frequently, in which case |
bos@683 | 817 you'll need to do a little scripting to refresh the list of |
bos@683 | 818 repositories to back up.</para> |
bos@683 | 819 |
bos@684 | 820 <para id="x_6d9">If you perform traditional backups of your master |
bos@683 | 821 repositories to tape or disk, and you want to back up a |
bos@701 | 822 repository named <filename>myrepo</filename>, use <command>hg |
bos@683 | 823 clone -U myrepo myrepo.bak</command> to create a |
bos@683 | 824 clone of <filename>myrepo</filename> before you start your |
bos@683 | 825 backups. The <option>-U</option> option doesn't check out a |
bos@683 | 826 working directory after the clone completes, since that would be |
bos@685 | 827 superfluous and make the backup take longer.</para> |
bos@683 | 828 |
bos@684 | 829 <para id="x_6da">If you then back up <filename>myrepo.bak</filename> instead |
bos@683 | 830 of <filename>myrepo</filename>, you will be guaranteed to have a |
bos@683 | 831 consistent snapshot of your repository that won't be pushed to |
bos@683 | 832 by an insomniac developer in mid-backup.</para> |
bos@683 | 833 </sect1> |
bos@559 | 834 </chapter> |
bos@559 | 835 |
bos@559 | 836 <!-- |
bos@559 | 837 local variables: |
bos@559 | 838 sgml-parent-document: ("00book.xml" "book" "chapter") |
bos@559 | 839 end: |
bos@559 | 840 --> |