Skip to content

Rhaptos Software Development

Personal tools
You are here: Home » Documentation » Developer Documentation » Branch Management with svnmerge

Branch Management with svnmerge

Document Actions
The SVN merge facilities are pretty dumb, and doing merges, especially to long-lived branches, is annoying. There is an SVN helper tool called (a bit unhelpfully) 'svnmerge', and it is used for most new branches.

You can get svnmerge from the official source, or from the Debian package subversion-tools. The Debian version is pretty old, though, so I recommend getting the newest version from the website and "installing" it in /usr/local/bin or something.

Read up on the project website, too, but here's the skinny: svnmerge keeps track of the versions of some source already merged into a target. It does this through a SVN property, but that doesn't matter so much. You can ask it, once it's tracking this information, to merge some or all non-merged versions of the source into the target branch. When it does this, it will update its tracking of what's already merged. This is a lot easier than always searching through the svn log for the last merge from trunk, or even keeping up a tag of the last merge point as I suggested earlier.

Working on a Branch

Normally you start tracking a branch upon its creation, when it's equal to the trunk, with a simple::

$ svnmerge init

It will record that all versions from 0 to now have been merged to this branch. If you have a branch that has already been created (like the dozens of plone25 branches) then you have to manually tell it the revisions that have already been merged, namely 0 to the last time we merged from trunk. Yes, this means

$ svn log --stop-on-copy | less

...but only once for the life of this branch.

So we find the last time we were synced with trunk (either creation or the last merge from trunk) and initialize tracking with::

$ svnmerge init -r0-XXXXX

where XXXXX is the version we extracted from the log. If the branch was copied from a trunk which isn't managed from svnmerge (and none are at the moment) you may have to override the svnmerge properties forcibly::

$ svnmerge init -r0-XXXXX --force


The svnmerge command is always meant to be run from the top of the working directory that is being merged to, by the way. Then we commit the tracking changes, preferably along with the helpful commit message svnmerge creates::

$ svn ci -F svnmerge-commit-message.txt
$ rm svnmerge-commit-message.txt

In other circumstances, the commit message becomes quite large, copying the logs of all the merged changes. I don't know that we want to check those in; it might be helpful, but I'm going to not do so for now.

Now that svnmerge is tracking this branch, we can ask it what changes are available on the source (trunk) to merge into this branch::

$ svnmerge avail

But usually we just want to merge all the new stuff from trunk, so we say::

$ svnmerge merge

It will update the current working directory with the merged changes. Examine the changes, resolve any conflicts, and then commit the changes, which will update svnmerge tracking info. If there are no merged changes, you don't have to do anything, of course.

$ svn st
$ svn diff
$ svn ci -m"merge from trunk with svnmerge; picked up ..."

(Don't use the svnmerge-commit-message.txt; it doesn't play well with Trac's SVN integration because a string like 'fix #1111', as included in the list of merged commit messages, causes the ticket to be re-opened into 'testing'.)

Subsequent merges to that branch won't require so much work, just the last steps of svnmerge merge, check the diff, and commit.

That's pretty nice, huh?

Merging to trunk (or another branch)

svnmerge can also be used for merging branches to trunk, using a similar technique, and the project site documents that nicely. It's a few more steps than the traditional manner (merging to trunk is easier in regular SVN than from trunk) but the bidirectional merge has much less thinking involved (and could probably be scripted easily). Here's what a merge to trunk from a controlled branch looks like:

cd BRANCHNAME_IN_DEVSET

Make sure it's clean:

svn st

Get the branch URL:

svn info

Get onto trunk (svnmerge always wants to run from the place it's changing):

svn switch svn+ssh://software.cnx.rice.edu/.../trunk

Say we're going to merge from such-and-such branch (can be copied directly from the svn info above):

svnmerge init svn+ssh://software.cnx.rice.edu/.../branches/BRANCHNAME
svn ci -F svnmerge-commit-message.txt

Do the merge (if there's more than one branch watched, as per init above, you'll have to use -S BRANCHNAME to specify):

svnmerge merge --bidirectional

Make sure it's all done right:

svn st
svn diff

Commit the merge:

svn ci -m"merged XXX branch to trunk; includes the new feature..."

(Don't use the svnmerge-commit-message.txt; it doesn't play well with Trac's SVN integration, as 'fix #1111' causes the ticket to be re-opened into 'testing'.)

Then, stop trunk from watching that branch (unless you may be merging again in the near future):

svnmerge uninit -S BRANCHNAME
svn ci -F svnmerge-commit-message.txt
rm svnmerge-commit-message.txt

Finally...

Please continue to use svnmerge on any branch that already uses it; if you're not sure, ask whomever created/maintains the branch. (There's also a svn:externals property you can check. It should be 'svnmerge-integrated'.)

Created by jccooper
Last modified 2008-04-14 10:32