Mercurial > hgbook
diff en/ch04-daily.xml @ 773:3b640272a966
Progres on resolve
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Sun, 12 Apr 2009 00:05:30 -0700 |
parents | b338f5490029 |
children | 29f0f79cf614 |
line wrap: on
line diff
--- a/en/ch04-daily.xml Thu Apr 09 22:54:10 2009 -0700 +++ b/en/ch04-daily.xml Sun Apr 12 00:05:30 2009 -0700 @@ -26,14 +26,14 @@ <para id="x_1a5">After you run a <command role="hg-cmd">hg commit</command>, the files that you added before the commit will no longer be listed in the output of <command role="hg-cmd">hg - status</command>. The reason for this is that <command + status</command>. The reason for this is that by default, <command role="hg-cmd">hg status</command> only tells you about - <quote>interesting</quote> files&emdash;those that you have - modified or told Mercurial to do something with&emdash;by - default. If you have a repository that contains thousands of - files, you will rarely want to know about files that Mercurial - is tracking, but that have not changed. (You can still get this - information; we'll return to this later.)</para> + <quote>interesting</quote> files&emdash;those that you have (for + example) modified, removed, or renamed. If you have a repository + that contains thousands of files, you will rarely want to know + about files that Mercurial is tracking, but that have not + changed. (You can still get this information; we'll return to + this later.)</para> <para id="x_1a6">Once you add a file, Mercurial doesn't do anything with it immediately. Instead, it will take a snapshot of the file's @@ -51,15 +51,15 @@ &interaction.daily.files.add-dir; - <para id="x_1a8">Notice in this example that Mercurial printed the names of - the files it added, whereas it didn't do so when we added the - file named <filename>a</filename> in the earlier - example.</para> + <para id="x_1a8">Notice in this example that Mercurial printed + the names of the files it added, whereas it didn't do so when + we added the file named <filename>myfile.txt</filename> in the + earlier example.</para> <para id="x_1a9">What's going on is that in the former case, we explicitly - named the file to add on the command line, so the assumption - that Mercurial makes in such cases is that you know what you - were doing, and it doesn't print any output.</para> + named the file to add on the command line. The assumption + that Mercurial makes in such cases is that we know what we + are doing, and it doesn't print any output.</para> <para id="x_1aa">However, when we <emphasis>imply</emphasis> the names of files by giving the name of a directory, Mercurial takes the @@ -67,8 +67,8 @@ something with. This makes it more clear what is happening, and reduces the likelihood of a silent and nasty surprise. This behavior is common to most Mercurial commands.</para> + </sect2> - </sect2> <sect2> <title>Mercurial tracks files, not directories</title> @@ -102,15 +102,15 @@ <para id="x_1ae">Another way to tackle a need for an empty directory is to simply create one in your automated build scripts before they will need it.</para> - </sect2> </sect1> + <sect1> <title>How to stop tracking a file</title> <para id="x_1af">Once you decide that a file no longer belongs in your repository, use the <command role="hg-cmd">hg remove</command> - command; this deletes the file, and tells Mercurial to stop + command. This deletes the file, and tells Mercurial to stop tracking it. A removed file is represented in the output of <command role="hg-cmd">hg status</command> with a <quote><literal>R</literal></quote>.</para> @@ -140,15 +140,16 @@ <para id="x_1b4">Removing a file <emphasis>does not</emphasis> in any way alter the <emphasis>history</emphasis> of the file.</para> - <para id="x_1b5">If you update the working directory to a changeset in - which a file that you have removed was still tracked, it will - reappear in the working directory, with the contents it had - when you committed that changeset. If you then update the - working directory to a later changeset, in which the file had - been removed, Mercurial will once again remove the file from - the working directory.</para> + <para id="x_1b5">If you update the working directory to a + changeset that was committed when it was still tracking a file + that you later removed, the file will reappear in the working + directory, with the contents it had when you committed that + changeset. If you then update the working directory to a + later changeset, in which the file had been removed, Mercurial + will once again remove the file from the working + directory.</para> + </sect2> - </sect2> <sect2> <title>Missing files</title> @@ -177,9 +178,9 @@ name of the file to recover. It will reappear, in unmodified form.</para> -&interaction.daily.files.recover-missing; + &interaction.daily.files.recover-missing; + </sect2> - </sect2> <sect2> <title>Aside: why tell Mercurial explicitly to remove a file?</title> @@ -192,8 +193,8 @@ commit</command>, and stop tracking the file. In practice, this made it too easy to accidentally remove a file without noticing.</para> + </sect2> - </sect2> <sect2> <title>Useful shorthand&emdash;adding and removing files in one step</title> @@ -210,9 +211,9 @@ followed by a commit.</para> &interaction.daily.files.commit-addremove; - </sect2> </sect1> + <sect1> <title>Copying files</title> @@ -272,14 +273,14 @@ into its copy, <filename>new-file</filename>.</para> &interaction.daily.copy.merge; + </sect2> - </sect2> <sect2 id="sec:daily:why-copy"> <title>Why should changes follow copies?</title> - <para id="x_1c4">This behavior, of changes to a file propagating out to - copies of the file, might seem esoteric, but in most cases - it's highly desirable.</para> + <para id="x_1c4">This behavior&emdash;of changes to a file + propagating out to copies of the file&emdash;might seem + esoteric, but in most cases it's highly desirable.</para> <para id="x_1c5">First of all, remember that this propagation <emphasis>only</emphasis> happens when you merge. So if you @@ -288,8 +289,8 @@ of your work, nothing will happen.</para> <para id="x_1c6">The second thing to know is that modifications will only - propagate across a copy as long as the repository that you're - pulling changes from <emphasis>doesn't know</emphasis> about + propagate across a copy as long as the changeset that you're + merging changes from <emphasis>hasn't yet seen</emphasis> the copy.</para> <para id="x_1c7">The reason that Mercurial does this is as follows. Let's @@ -301,8 +302,8 @@ <para id="x_1c8">If you pulled and merged my changes, and Mercurial <emphasis>didn't</emphasis> propagate changes across copies, - your source file would now contain the bug, and unless you - remembered to propagate the bug fix by hand, the bug would + your new source file would now contain the bug, and unless you + knew to propagate the bug fix by hand, the bug would <emphasis>remain</emphasis> in your copy of the file.</para> <para id="x_1c9">By automatically propagating the change that fixed the bug @@ -315,9 +316,9 @@ subsequent merge occurred, there's usually no further need to propagate changes from the original file to the copied file, and that's why Mercurial only propagates changes across copies - until this point, and no further.</para> + at the first merge, and not afterwards.</para> + </sect2> - </sect2> <sect2> <title>How to make changes <emphasis>not</emphasis> follow a copy</title> @@ -335,7 +336,7 @@ </sect2> <sect2> - <title>Behaviour of the <command role="hg-cmd">hg copy</command> + <title>Behavior of the <command role="hg-cmd">hg copy</command> command</title> <para id="x_1cc">When you use the <command role="hg-cmd">hg copy</command> @@ -348,14 +349,17 @@ behavior a little counterintuitive, which is why I mention it here.)</para> - <para id="x_1cd">The <command role="hg-cmd">hg copy</command> command acts - similarly to the Unix <command>cp</command> command (you can - use the <command role="hg-cmd">hg cp</command> alias if you - prefer). The last argument is the - <emphasis>destination</emphasis>, and all prior arguments are - <emphasis>sources</emphasis>. If you pass it a single file as - the source, and the destination does not exist, it creates a - new file with that name.</para> + <para id="x_1cd">The <command role="hg-cmd">hg copy</command> + command acts similarly to the Unix <command>cp</command> + command (you can use the <command role="hg-cmd">hg + cp</command> alias if you prefer). We must supply two or + more arguments, of which the last is treated as the + <emphasis>destination</emphasis>, and all others are + <emphasis>sources</emphasis>.</para> + + <para>If you pass <command role="hg-cmd">hg copy</command> a + single file as the source, and the destination does not exist, + it creates a new file with that name.</para> &interaction.daily.copy.simple; @@ -375,16 +379,16 @@ &interaction.daily.copy.dir-src-dest; - <para id="x_1d1">As with the <command role="hg-cmd">hg rename</command> + <para id="x_1d1">As with the <command role="hg-cmd">hg remove</command> command, if you copy a file manually and then want Mercurial to know that you've copied the file, simply use the <option role="hg-opt-copy">--after</option> option to <command role="hg-cmd">hg copy</command>.</para> &interaction.daily.copy.after; - </sect2> </sect1> + <sect1> <title>Renaming files</title> @@ -426,6 +430,11 @@ similar to the <command role="hg-cmd">hg copy</command> command.</para> + <para>If you're familiar with the Unix command line, you'll be + glad to know that <command role="hg-cmd">hg rename</command> + command can be invoked as <command role="hg-cmd">hg + mv</command>.</para> + <sect2> <title>Renaming files and merging changes</title> @@ -446,8 +455,8 @@ rename is definitely important. Without this facility, it would simply be too easy for changes to become orphaned when files are renamed.</para> + </sect2> - </sect2> <sect2> <title>Divergent renames and merging</title> @@ -463,7 +472,9 @@ &interaction.rename.divergent.rename.anne; <para id="x_1dc">Meanwhile, Bob renames it to - <filename>quux</filename>.</para> + <filename>quux</filename>. (Remember that <command + role="hg-cmd">hg mv</command> is an alias for <command + role="hg-cmd">hg rename</command>.)</para> &interaction.rename.divergent.rename.bob; @@ -478,11 +489,11 @@ &interaction.rename.divergent.merge; - <para id="x_1df">Notice that Mercurial does warn about the divergent - renames, but it leaves it up to you to do something about the + <para id="x_1df">Notice that while Mercurial warns about the divergent + renames, it leaves it up to you to do something about the divergence after the merge.</para> + </sect2> - </sect2> <sect2> <title>Convergent renames and merging</title> @@ -491,8 +502,8 @@ to the same <emphasis>destination</emphasis>. In this case, Mercurial runs its normal merge machinery, and lets you guide it to a suitable resolution.</para> + </sect2> - </sect2> <sect2> <title>Other name-related corner cases</title> @@ -507,6 +518,7 @@ </sect2> </sect1> + <sect1> <title>Recovering from mistakes</title> @@ -523,7 +535,7 @@ <command role="hg-cmd">hg revert</command> to get rid of erroneous changes to a file.</para> - <para id="x_1e4">It's useful to remember that the <command role="hg-cmd">hg + <para id="x_1e4">It's good to remember that the <command role="hg-cmd">hg revert</command> command is useful for changes that you have not yet committed. Once you've committed a change, if you decide it was a mistake, you can still do something about it, @@ -533,7 +545,133 @@ role="hg-cmd">hg revert</command> command, and details about how to deal with changes you have already committed, see <xref linkend="chap:undo"/>.</para> + </sect1> + <sect1> + <title>Dealing with tricky merges</title> + + <para>In a complicated or large project, it's not unusual for a + merge of two changesets to result in some headaches. Suppose + there's a big source file that's been extensively edited by each + side of a merge: this is almost inevitably going to result in + conflicts, some of which can take a few tries to sort + out.</para> + + <para>Let's develop a simple case of this and see how to deal with + it. We'll start off with a repository containing one file, and + clone it twice.</para> + + &interaction.ch04-resolve.init; + + <para>In one clone, we'll modify the file in one way.</para> + + &interaction.ch04-resolve.left; + + <para>In another, we'll modify the file differently.</para> + + &interaction.ch04-resolve.right; + + <para>Next, we'll pull each set of changes into our original + repo.</para> + + &interaction.ch04-resolve.pull; + + <para>We expect our repository to now contain two heads.</para> + + &interaction.ch04-resolve.heads; + + <para>Normally, if we run <command role="hg-cmd">hg + merge</command> at this point, it will drop us into a GUI that + will let us manually resolve the conflicting edits to + <filename>myfile.txt</filename>. However, to simplify things + for presentation here, we'd like the merge to fail immediately + instead. Here's one way we can do so.</para> + + &interaction.ch04-resolve.export; + + <para>We've told Mercurial's merge machinery to run the command + <command>false</command> (which, as we desire, fails + immediately) if it detects a merge that it can't sort out + automatically.</para> + + <para>If we now fire up <command role="hg-cmd">hg + merge</command>, it should grind to a halt and report a + failure.</para> + + &interaction.ch04-resolve.merge; + + <para>Even if we don't notice that the merge failed, Mercurial + will prevent us from accidentally committing the result of a + failed merge.</para> + + &interaction.ch04-resolve.cifail; + + <para>When <command role="hg-cmd">hg commit</command> fails in + this case, it suggests that we use the unfamiliar <command + role="hg-cmd">hg resolve</command> command. As usual, + <command role="hg-cmd">hg help resolve</command> will print a + helpful synopsis.</para> + + <sect2> + <title>File resolution states</title> + + <para>When a merge occurs, most files will usually remain + unmodified. For each file where Mercurial has to do + something, it tracks the state of the file.</para> + + <itemizedlist> + <listitem> + <para>A <emphasis>resolved</emphasis> file has been + successfully merged, either automatically by Mercurial or + manually with human intervention.</para> + </listitem> + <listitem> + <para>An <emphasis>unresolved</emphasis> file was not merged + successfully, and needs more attention.</para> + </listitem> + </itemizedlist> + + <para>If Mercurial sees <emphasis>any</emphasis> file in the + unresolved state after a merge, it considers the merge to have + failed. Fortunately, we do not need to restart the entire + merge from scratch.</para> + + <para>The <option role="hg-opt-resolve">--list</option> or + <option role="hg-opt-resolve">-l</option> option to <command + role="hg-cmd">hg resolve</command> prints out the state of + each merged file.</para> + + &interaction.ch04-resolve.list; + + <para>In the output from <command role="hg-cmd">hg + resolve</command>, a resolved file is marked with + <literal>R</literal>, while an unresolved file is marked with + <literal>U</literal>. If any files are listed with + <literal>U</literal>, we know that an attempt to commit the + results of the merge will fail.</para> + </sect2> + + <sect2> + <title>Resolving a file merge</title> + + <para>We have several options to move a file from the unresolved + into the resolved state. By far the most common is to rerun + <command role="hg-cmd">hg resolve</command>. If we pass the + names of individual files or directories, it will retry the + merges of any unresolved files present in those locations. We + can also pass the <option role="hg-opt-resolve">--all</option> + or <option role="hg-opt-resolve">-a</option> option, which + will retry the merges of <emphasis>all</emphasis> unresolved + files.</para> + + <para>Mercurial also lets us modify the resolution state of a + file directly. We can manually mark a file as resolved using + the <option role="hg-opt-resolve">--mark</option> option, or + as unresolved using the <option + role="hg-opt-resolve">--unmark</option> option. This allows + us to clean up a particularly messy merge by hand, and to keep + track of our progress with each file as we go.</para> + </sect2> </sect1> </chapter>