By this time, I assume you already understand why we can’t simply merge HEAD revision and assume that we’ll get everything. If you don’t get it, go back to page 1 of this article. I also assume that you know the basic concept of merging. If you don’t please glance through page 2 of this article.
Merging with svnmerge.py
As mentioned on page 2, svnmerge.py is basically a script that automates the merging process by finding which revisions needed to be applied. I’m not gonna dwell too much about what svnmerge.py is. If you’ve read page 2 of this article, you would have some ideas as to what it does. Let’s just jump to how to use it. It’s always better to show by example anyway, right?
Taking care of requirements of svnmerge.py
svnmerge.py requires svn version 1.1 or above and Python 2.o or later. To find out what version your svn is, do svn –version on the command line. To find out which python is installed, type python –version on command line. If you’re on Windows, there’s a windows binary svnmerge.exe available. (what are you doing developing on Windows to begin with ???
) If your system is missing any of the requirements, do take care of installing them first. Install svn or python is beyond the scope of this article. Google it! I’m sure there are tons of articles already on how to install svn client or python.
Once you have all the requirements down, download svnmerge.py here. Make some necessary changes to the file permission to it and you’re set.
Initializing branch for merge tracking
So in order for svnmerge.py to be able to track merges and changes, it first needs to know the starting revision. svnmerge.py cleverly uses the commit messages to store its information. The plus point of doing that is that there is no need to manage separate database as the information itself is built-in (sort of) to svn. The consequence: you have to commit to actually save the “data” to the database (svn).
Having said that, the first thing that you need to do so that svnmerge.py can track changes is to initialize the branch. I think it’s a good practice to immediately track changes as part of the process of creating branch. So when creating branch session would look like below:
user@dev:~/work/TRUNK$ svn copy http://localhost/svn/tutorial/TRUNK/ \ http://localhost/svn/tutorial/mine -m "Creating my branch" user@dev:~/work/TRUNK$ cd .. user@dev:~/work$ svn checkout http://localhost/svn/tutorial/mine/ A mine/testfile.php Checked out revision 5. user@dev:~/work$ cd mine user@dev:~/work/mine$ svnmerge.py init http://localhost/svn/tutorial/TRUNK/ property 'svnmerge-integrated' set on '.' user@dev:~/work/mine$ svn status ? svnmerge-commit-message.txt M . user@dev:~/work/mine$ cat svnmerge-commit-message.txt Initialized merge tracking via "svnmerge" with revisions "1-2" from http://localhost/svn/tutorial/TRUNK user@dev:~/work/mine$ svn commit -F svnmerge-commit-message.txt Sending . Committed revision 6. user@dev:~/work/mine$ rm svnmerge-commit-message.txt
If you’re going to merge TRUNK and mine branch back and forth, it’s also recommended to do merge tracking on TRUNK between TRUNK and mine branch.
user@dev:~/work/mine$ cd ../TRUNK/ user@dev:~/work/TRUNK$ svn update At revision 6. user@dev:~/work/TRUNK$ svnmerge.py init http://localhost/svn/tutorial/mine/ property 'svnmerge-integrated' set on '.' user@dev:~/work/TRUNK$ cat svnmerge-commit-message.txt Initialized merge tracking via "svnmerge" with revisions "1-3" from http://localhost/svn/tutorial/mine user@dev:~/work/TRUNK$ svn commit -F svnmerge-commit-message.txt Sending . Committed revision 7. user@dev:~/work/TRUNK$ rm svnmerge-commit-message.txt
Updating branch with the latest TRUNK changes
Now that we have the merge tracking properties set on both branches, let’s see what’s available in mine branch to be merged.
user@dev:~/work/mine$ svnmerge.py avail 4-5 user@dev:~/work/mine$
Alright! svnmerge.py is smart enough to know what revisions I need to apply. Let’s actually apply those revisions and commit it. Notice that we now have both line 2 and 3 changed appropriately.
user@dev:~/work/mine$ svnmerge.py merge
property 'svnmerge-integrated' deleted from '.'.
U testfile.php
property 'svnmerge-integrated' set on '.'
user@dev:~/work/mine$ cat svnmerge-commit-message.txt
Merged revisions 4-5 via svnmerge from
http://localhost/svn/tutorial/TRUNK
........
r4 | user | 2009-04-03 13:12:15 -0700 (Fri, 03 Apr 2009) | 1 line
Changed line 2
........
r5 | user | 2009-04-03 13:13:06 -0700 (Fri, 03 Apr 2009) | 1 line
Changed line 3
........
user@dev:~/work/mine$ svnmerge.py
user@dev:~/work/mine$ svn commit -F svnmerge-commit-message.txt
Sending .
Sending testfile.php
Transmitting file data .
Committed revision 8.
user@dev:~/work/mine$ rm svnmerge-commit-message.txt
user@dev:~/work/mine$ cat testfile.php
<?php
function my_add($num) {
$add_by = 5;
return ($num + $add_by) * -1;
}
user@dev:~/work/mine$
Merging branch changes back to TRUNK
Here’s my session on changing the file in branch, committing them, then go to TRUNK branch and get an update. Notice that svnmerge.py is smart enough that revision 8 that was committed to mine branch is a merge commit and thus, not including it as part of revision changes to be applied.
user@dev:~/work/mine$ cat testfile.php
<?php
function my_add($num, $multiplier = null) {
if (empty($multiplier)) return false;
return $num * $multiplier;
}
user@dev:~/work/mine$ svn status
M testfile.php
user@dev:~/work/mine$ svn commit -m "Made some changes in branch"
Sending testfile.php
Transmitting file data .
Committed revision 9.
user@dev:~/work/mine$ cd ../TRUNK/
user@dev:~/work/TRUNK$ svnmerge.py avail
9
user@dev:~/work/TRUNK$ cat testfile.php
<?php
function my_add($num) {
$add_by = 5;
return ($num + $add_by) * -1;
}
user@dev:~/work/TRUNK$ svnmerge.py merge
property 'svnmerge-integrated' set on '.'
U testfile.php
property 'svnmerge-integrated' set on '.'
user@dev:~/work/TRUNK$ cat testfile.php
<?php
function my_add($num, $multiplier = null) {
if (empty($multiplier)) return false;
return $num * $multiplier;
}
user@dev:~/work/TRUNK$ svn commit -F svnmerge-commit-message.txt
Sending .
Sending testfile.php
Transmitting file data .
Committed revision 10.
user@dev:~/work/TRUNK$ rm svnmerge-commit-message.txt
Extended use cases
When merge tracking has more than 1 source branch that it can look into, you need to tell svnmerge.py which branch you want to do the merging on. This is quite common if you have 2 branches: mine and yours, and both of them are tracked in TRUNK, when you want to merge in TRUNK you have to tell svnmerge.py whether you want to merge mine branch or yours branch. This could be done by passing -S option to svnmerge.py.
user@dev:~/work/TRUNK$ svnmerge.py -S http://localhost/svn/tutorial/mine/
There are times when a branch development is done and that we don’t need that branch anymore. If that’s the case, you can remove merge tracking information so that when you do svnmerge.py, you don’t have to pass -S options all the time or minimize the branches that can be merged, and overall to keep things clean.
user@dev:~/work/TRUNK$ svnmerge.py uninit \ -S http://localhost/svn/tutorial/mine property 'svnmerge-integrated' deleted from '.'. user@dev:~/work/TRUNK$ cat svnmerge-commit-message.txt Removed merge tracking for "svnmerge" for http://localhost/svn/tutorial/mine user@dev:~/work/TRUNK$ svn commit -F svnmerge-commit-message.txt Sending . Committed revision 11. user@dev:~/work/TRUNK$ rm svnmerge-commit-message.txt
There you have it … I hope you enjoyed this article. Please leave comments / suggestions / questions if you have. I’m looking forward to improving my solution with your comments / suggestions / questions.







I think this is not needed woth svn 1.6.x, because it saves merge history in the svn:property mergeinfo.
Am I wrong ?
Yes … SVN 1.6.x does support merging .. hence we don’t have to use svnmerge.py anymore. There are plenty of cases where distributions doesn’t have SVN 1.6 yet. In particular Ubuntu Hardy (the distribution I’m using). Even if you’re using SVN 1.6, it doesn’t mean that you can’t still use svnmerge.py though. I have a feeling that I would still be using svnmerge.py even though I’m using SVN 1.6 just because I’m already familiar with it. Maybe once svnmerge.py is no longer maintained, I’d be forced to use SVN 1.6 built in merging feature