hgbook
annotate en/ch05-daily.xml @ 890:2887b61fa4fe
Change fields to fieldsets in the Comment admin model. The 'date'
field isn't working properly for an unknown reason, so it has been
removed from the interface temporarily.
field isn't working properly for an unknown reason, so it has been
removed from the interface temporarily.
author | dukebody <dukebody@gmail.com> |
---|---|
date | Sun Oct 11 21:12:46 2009 +0200 (2009-10-11) |
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 --> |