This section is from the "Version Control with Subversion" book, by Ben Collins-Sussman, Brian W. Fitzpatrick and C. Michael Pilato. Also available from Amazon: Version Control with Subversion.
One of the main features of any version control system is to keep track of who changed what, and when they did it. The svn log and svn blame 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.
When changes start getting replicated between branches, however, things start to get complicated. For example, if you were to ask svn log about the history of your feature branch, it shows exactly every revision that ever affected the branch:
$ 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 ------------------------------------------------------------------------
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.
$ 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.
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
--use-merge-history (-g)
option. This option expands those “child”
changes that were part of the merge.
$ 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.
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!
The svn blame command also takes the
--use-merge-history (-g)
option. If this option is neglected, then somebody looking at
a line-by-line annotation of button.c may
get the mistaken impression that you were responsible for the
lines that fixed a certain error:
$ svn blame button.c ... 390 user retval = inverse_func(button, path); 390 user return retval; 390 user } ...
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:
$ svn blame button.c -g
...
G 383 sally retval = inverse_func(button, path);
G 383 sally return retval;
390 user }
...
Now we know who to really blame for those two lines of code!