4.9 Merging a Branch
As various branches of a repository's main trunk progress and diverge, it's sometimes necessary to use changes made on one branch in a different branch. Subversion allows you to apply these changes using the merge command. Let's say you add a line of output to the Hello World program to make it output some copyright information so that it now looks like this:
#include <stdio.h> int main(int argc, char** argv) { printf("Subversion Rocks!!\n"); printf("Copyright 2004, Bill Nagel\n"); return 0; }
This change is of course committed as usual, using svn commit.
$ svn commit --message "Added copyright information" Sending hello.c Transmitting file data . Committed revision 6.
Because outputting the copyright information is something that would be useful in both your Subversion-praising version and in the CVS-praising branch, it would be nice to merge these changes over to the branch. To do this, you'll use the svn merge command.
The merge command works by taking the difference between two revisions of a file or directory in the repository and applying those differences to a location in your working directory. In this case, you want to apply the change made to the repository trunk in revision 6 to the cvs_version branch.
First, you should run svn log to check which revision(s) of the repository the change you want to merge was committed on.
$ svn log hello.c ---------------------------------------------------------------- r6 | bill | 2004-07-13 00:23:38 -0500 (Tue, 13 Jul 2004) | 1 line Added copyright information ---------------------------------------------------------------- r2 | bill | 2004-07-11 04:45:12 -0500 (Sun, 11 Jul 2004) | 1 line Changed program output ---------------------------------------------------------------- r1 | bill | 2004-07-08 16:28:57 -0500 (Thu, 08 Jul 2004) | 1 line Initial import ----------------------------------------------------------------
In this case, you can see that the copyright information change was applied to the main trunk in revision 6. That means that to apply those changes to the branch version, you need to apply the difference between revision 6 of hello.c and revision 5.
The Subversion merge command takes as parameters two different revisions of a source directory, and a working copy path to apply the changes to. Although merges are relatively easy to undo, after you have run them, it is usually a good idea to execute the merge command first with the --dry-run option, which will show you the files that will be changed before it applies the change. This lets you see any potential merge conflicts before they happen, which can often make them easier to deal with, and may even allow you to eliminate the conflict before it occurs. After the merge, it is a good idea to test the merged files and make sure everything was applied correctly, before committing the merge to the repository.
To run the merge in your repository, you can do the following.
$ svn switch file:///home/bill/my_repository/branches/cvs_version/ U hello.c Updated to revision 7. $ svn merge --dry-run -r 5:6 file:///home/bill/my_repository/trunk U hello.c $ svn merge --revision 5:6 file:///home/bill/my_repository/trunk U hello.c $ cat hello.c #include <stdio.h> int main(int argc, char** argv) { printf("CVS is the best!!\n"); // Ugh! The boss made me do it printf("Copyright 2004, Bill Nagel\n"); return 0; } $ svn commit --message "Merged with revision 6 - revision 5 in trunk/hello.c" Sending hello.c Transmitting file data . Committed revision 7. $ svn switch file:///home/bill/my_repository/trunk U hello.c Updated to revision 7.
You may notice that I explicitly stated in my log file for the merge commit which revisions were merged with the branch. It is actually very important to keep that information in the logs whenever a commit is made, because Subversion doesn't yet do any sort of tracking of merges and branches. By keeping track of the merged revisions in the logs, you can help ensure that you don't accidentally apply a merge more than once, which can have the unintended side effects of triggering spurious conflicts or even putting back changes that were taken out previously.