Branch Management with svnmerge
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'.)
