[svnbook commit] r2915 - trunk/src/en/book

sussman noreply at red-bean.com
Thu Dec 13 23:09:34 CST 2007


Author: sussman
Date: Thu Dec 13 23:09:32 2007
New Revision: 2915

Log:
Keep filling out chapter 4.

* src/en/book/ch04-branching-and-merging.xml:  document log/blame -g



Modified:
   trunk/src/en/book/ch04-branching-and-merging.xml

Modified: trunk/src/en/book/ch04-branching-and-merging.xml
==============================================================================
--- trunk/src/en/book/ch04-branching-and-merging.xml	(original)
+++ trunk/src/en/book/ch04-branching-and-merging.xml	Thu Dec 13 23:09:32 2007
@@ -1373,180 +1373,9 @@
 
     </sect2>
 
-    <!-- =============================================================== -->
-    <sect2 id="svn.branchmerge.advanced.manual">
-      <title>Manually Merging a Branch</title>
-
-      <para>###TODO: if basic merge tracking isn't available (client
-        or server is older than 1.5), then here is the 'manual' method
-        for keeping a private branch in sync with trunk, and how to
-        merge it back into trunk:</para>
-
-      <para>To complete our running example, we'll move forward in
-        time.  Suppose several days have passed, and many changes have
-        happened on both the trunk and your private branch.  Suppose
-        that you've finished working on your private branch; the
-        feature or bug fix is finally complete, and now you want to
-        merge all of your branch changes back into the trunk for
-        others to enjoy.</para>
-
-      <para>So how do we use <command>svn merge</command> in this
-        scenario?  Remember that this command compares two trees, and
-        applies the differences to a working copy.  So to receive the
-        changes, you need to have a working copy of the trunk.  We'll
-        assume that either you still have your original one lying
-        around (fully updated), or that you recently checked out a
-        fresh working copy of <filename>/calc/trunk</filename>.</para>
-
-      <para>But which two trees should be compared?  At first glance,
-        the answer may seem obvious: just compare the latest trunk
-        tree with your latest branch tree.  But beware—this
-        assumption is <emphasis>wrong</emphasis>, and has burned many
-        a new user!  Since <command>svn merge</command> operates like
-        <command>svn diff</command>, comparing the latest trunk and 
-        branch trees will <emphasis>not</emphasis> merely describe
-        the set of changes you made to your branch.  Such a comparison
-        shows too many changes: it would not only show the addition of
-        your branch changes, but also the <emphasis>removal</emphasis>
-        of trunk changes that never happened on your branch.</para>
-
-      <para>To express only the changes that happened on your branch,
-        you need to compare the initial state of your branch to its
-        final state.  Using <command>svn log</command> on your branch,
-        you can see that your branch was created in revision 341.  And
-        the final state of your branch is simply a matter of using the
-        <literal>HEAD</literal> revision.  That means you want to
-        compare revisions 341 and <literal>HEAD</literal> of your
-        branch directory, and apply those differences to a working
-        copy of the trunk.</para>
-
-      <tip>
-        <para>A nice way of finding the revision in which a branch was
-          created (the <quote>base</quote> of the branch) is to use the
-          <option>--stop-on-copy</option> option to <command>svn
-          log</command>.  The log subcommand will normally show every
-          change ever made to the branch, including tracing back
-          through the copy which created the branch.  So normally,
-          you'll see history from the trunk as well.  The
-          <option>--stop-on-copy</option> will halt log output as soon
-          as <command>svn log</command> detects that its target was
-          copied or renamed.</para>
-
-        <para>So in our continuing example,</para>
-
-        <screen>
-$ svn log -v --stop-on-copy \
-          http://svn.example.com/repos/calc/branches/my-calc-branch
-…
-------------------------------------------------------------------------
-r341 | user | 2002-11-03 15:27:56 -0600 (Thu, 07 Nov 2002) | 2 lines
-Changed paths:
-   A /calc/branches/my-calc-branch (from /calc/trunk:340)
-
-$
-</screen>
-
-        <para>As expected, the final revision printed by this command
-          is the revision in which <filename>my-calc-branch</filename>
-          was created by copying.</para>
-      </tip>
-
-
-      <para>Here's the final merging procedure, then:</para>
-
-      <screen>
-$ cd calc/trunk
-$ svn update
-At revision 405.
-
-$ svn merge -r 341:405 http://svn.example.com/repos/calc/branches/my-calc-branch
-U   integer.c
-U   button.c
-U   Makefile
-
-$ svn status
-M   integer.c
-M   button.c
-M   Makefile
-
-# ...examine the diffs, compile, test, etc...
-
-$ svn commit -m "Merged my-calc-branch changes r341:405 into the trunk."
-Sending        integer.c
-Sending        button.c
-Sending        Makefile
-Transmitting file data ...
-Committed revision 406.
-</screen>
-
-      <para>Again, notice that the commit log message very
-        specifically mentions the range of changes that was merged
-        into the trunk.  Always remember to do this, because it's
-        critical information you'll need later on.</para>
-
-      <para>For example, suppose you decide to keep working on your
-        branch for another week, in order to complete an enhancement
-        to your original feature or bug fix.  The repository's
-        <literal>HEAD</literal> revision is now 480, and you're ready
-        to do another merge from your private branch to the trunk.
-        But don't want to merge the changes you've already merged
-        before; you only want to merge everything <quote>new</quote>
-        on your branch since the last time you merged.  The trick is
-        to figure out what's new.</para>
-
-      <para>The first step is to run <command>svn log</command> on the
-        trunk, and look for a log message about the last time you
-        merged from the branch:</para>
-
-      <screen>
-$ cd calc/trunk
-$ svn log
-…
-------------------------------------------------------------------------
-r406 | user | 2004-02-08 11:17:26 -0600 (Sun, 08 Feb 2004) | 1 line
-
-Merged my-calc-branch changes r341:405 into the trunk.
-------------------------------------------------------------------------
-…
-</screen>
-
-      <para>Aha!  Since all branch-changes that happened between
-        revisions 341 and 405 were previously merged to the trunk as
-        revision 406, you now know that you want to merge only the
-        branch changes after that—by comparing revisions 406 and
-        <literal>HEAD</literal>.</para>
-
-      <screen>
-$ cd calc/trunk
-$ svn update
-At revision 480.
-
-# We notice that HEAD is currently 480, so we use it to do the merge:
-
-$ svn merge -r 406:480 http://svn.example.com/repos/calc/branches/my-calc-branch
-U   integer.c
-U   button.c
-U   Makefile
-
-$ svn commit -m "Merged my-calc-branch changes r406:480 into the trunk."
-Sending        integer.c
-Sending        button.c
-Sending        Makefile
-Transmitting file data ...
-Committed revision 481.
-</screen>
-
-      <para>Now the trunk contains the complete second wave of changes
-        made to the branch.  At this point, you can either delete your
-        branch (we'll discuss this later on), or continue working on
-        your branch and repeat this procedure for subsequent
-        merges.</para>
-
-    </sect2>
-
     <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
     <sect2 id="svn.branchmerge.advanced.mergeconflicts">
-      <title>Merge Conflicts</title>
+      <title>More on Merge Conflicts</title>
 
       <para>Just like the <command>svn update</command> command,
         <command>svn merge</command> applies changes to your working
@@ -1580,15 +1409,15 @@
         will complain about <quote>skipped targets</quote>:</para>
 
       <screen>
-        $ svn merge -r 1288:1351 http://svn.example.com/repos/branch
-        U  foo.c
-        U  bar.c
-        Skipped missing target: 'baz.c'
-        U  glub.c
-        C  glorb.h
-
-        $
-      </screen>
+$ svn merge -r 1288:1351 http://svn.example.com/repos/branch
+U  foo.c
+U  bar.c
+Skipped missing target: 'baz.c'
+U  glub.c
+U  sputter.h
+Conflict discovered in 'glorb.h'.
+Select: (p)ostpone, (d)iff, (e)dit, (h)elp for more options : 
+</screen>
 
       <para>In the previous example it might be the case that
         <filename>baz.c</filename> exists in both snapshots of the
@@ -1649,10 +1478,133 @@
 
     <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
     <sect2 id="svn.branchmerge.advanced.logblame">
-      <title>Logging and Blaming</title>
+      <title>Merge-Sensitive Logs and Annotations</title>
+
+      <para>One of the main features of any version control system is
+        to keep track of who changed what, and when they did it.
+        The <command>svn log</command> and <command>svn
+        blame</command> commands are just the tools for this: when
+        invoked on individual files, they show not only the history of
+        changesets that affected the file, but exactly which user
+        wrote which line of code, and when they did it.</para>
+
+      <para>When changes start getting replicated between branches,
+        however, things start to get complicated.  For example, if you
+        were to ask <command>svn log</command> about the history of
+        your feature branch, it shows exactly every revision that ever
+        affected the branch:</para>
+
+      <screen>
+$ cd my-calc-branch
+$ svn log -q
+------------------------------------------------------------------------
+r390 | user | 2002-11-22 11:01:57 -0600 (Fri, 22 Nov 2002) | 1 line
+------------------------------------------------------------------------
+r388 | user | 2002-11-21 05:20:00 -0600 (Thu, 21 Nov 2002) | 2 lines
+------------------------------------------------------------------------
+r381 | user | 2002-11-20 15:07:06 -0600 (Wed, 20 Nov 2002) | 2 lines
+------------------------------------------------------------------------
+r359 | user | 2002-11-19 19:19:20 -0600 (Tue, 19 Nov 2002) | 2 lines
+------------------------------------------------------------------------
+r357 | user | 2002-11-15 14:29:52 -0600 (Fri, 15 Nov 2002) | 2 lines
+------------------------------------------------------------------------
+r343 | user | 2002-11-07 13:50:10 -0600 (Thu, 07 Nov 2002) | 2 lines
+------------------------------------------------------------------------
+r341 | user | 2002-11-03 07:17:16 -0600 (Sun, 03 Nov 2002) | 2 lines
+------------------------------------------------------------------------
+r303 | sally | 2002-10-29 21:14:35 -0600 (Tue, 29 Oct 2002) | 2 lines
+------------------------------------------------------------------------
+r98 | sally | 2002-02-22 15:35:29 -0600 (Fri, 22 Feb 2002) | 2 lines
+------------------------------------------------------------------------
+</screen>
+
+      <para>But is this really an accurate picture of all the changes
+        that happened on the branch?  What's being left out here is
+        the fact that revisions 390, 381, and 357 were actually the
+        results of merging changes from trunk.  If you look at a one
+        of these logs in detail, the multiple trunk changesets that
+        comprised the branch change are nowhere to be seen.</para>
+
+      <screen>
+$ svn log -v -r 390
+------------------------------------------------------------------------
+r390 | user | 2002-11-22 11:01:57 -0600 (Fri, 22 Nov 2002) | 1 line
+Changed paths:
+   M /branches/my-calc-branch/button.c
+   M /branches/my-calc-branch/README
+
+Final merge of trunk changes to my-calc-branch.
+</screen>
+
+      <para>We happen to know that this merge to the branch was
+        nothing but a merge of trunk changes.  How can we see those
+        trunk changes as well?  The answer is to use
+        the <option>--use-merge-history (-g)</option> option.  This
+        option expands those <quote>child</quote> changes that were
+        part of the merge.</para>
+
+      <screen>
+$ svn log -v -r 390 -g
+------------------------------------------------------------------------
+r390 | user | 2002-11-22 11:01:57 -0600 (Fri, 22 Nov 2002) | 1 line
+Changed paths:
+   M /branches/my-calc-branch/button.c
+   M /branches/my-calc-branch/README
+
+Final merge of trunk changes to my-calc-branch.
+------------------------------------------------------------------------
+r383 | sally | 2002-11-21 03:19:00 -0600 (Thu, 21 Nov 2002) | 2 lines
+Changed paths:
+   M /branches/my-calc-branch/button.c
+Result of a merge from: r390
+
+Fix inverse graphic error on button.
+------------------------------------------------------------------------
+r382 | sally | 2002-11-20 16:57:06 -0600 (Wed, 20 Nov 2002) | 2 lines
+Changed paths:
+   M /branches/my-calc-branch/README
+Result of a merge from: r390
+
+Document my last fix in README.
+</screen>
+
+      <para>By making the log operation use merge history, we see not
+        just the revision we queried (r390), but the two revisions
+        that came along on the ride with it—a couple of changes
+        made by Sally to the trunk.  This is a much more complete
+        picture of history!</para>
+
+      <para>The <command>svn blame</command> command also takes
+        the <option>--use-merge-history (-g)</option> option.  If this
+        option is neglected, then somebody looking at a line-by-line
+        annotation of <filename>button.c</filename> may get the
+        mistaken impression that you were responsible for the lines
+        that fixed a certain error:</para>
+
+      <screen>
+$ svn blame button.c
+...
+   390    user    retval = inverse_func(button, path);
+   390    user    return retval;
+   390    user    }
+...
+</screen>
+
+      <para>And while it's true that you did actually commit those
+        three lines in revision 390, two of them were actually writen
+        by Sally back in revision 383:</para>
+
+      <screen>
+$ svn blame button.c -g
+...
+G    383    sally   retval = inverse_func(button, path);
+G    383    sally   return retval;
+     390    user    }
+...
+</screen>
 
-      <para>###TODO:  demonstrate 'svn log -g' and 'svn blame -g', and
-        explain why they're useful.</para>
+      <para>Now we know who to <emphasis>really</emphasis> blame for
+        those two lines of code!</para>
 
     </sect2>
 




More information about the svnbook-dev mailing list