# First steps with Subversion’s new merge tracking

A while ago we succeeded in upgrading the Debian server where I keep many of my SVN repositories. (The server was running on “testing”, but we hadn’t dared to upgrade it for a long time until it came time to make it “stable” again with Lenny.) On of the upgraded packages in Lenny is Subversion, now at 1.5.1, which means that I can finally start using subversions new merge tracking features.

To be able to use merge tracking for my existing repositories, I first have to upgrade these. From the svn 1.5 release notes:

The Subversion 1.5 server works with 1.4 and older repositories, and it will not upgrade such repositories to 1.5 unless specifically requested to via the svnadmin upgrade command. This means that some of the new 1.5 features will not become available simply by upgrading your server: you will also have to upgrade your repositories. (We decided not to auto-upgrade repositories because we didn’t want 1.5 to silently make repositories unusable by 1.4 — that step should be a conscious decision on the part of the repository admin.)

The only other machine I’m using these repos from is my laptop, which, running Gentoo, is already at Subversion 1.6.2. So, how do I upgrade?

First, I made a backup of all our SVN repos using a script that Halfgaar made to run from cron. After running that script, I initialized the upgrade procedure:

/var/svn
svn-populate-node-origins-index blog.bigsmoke.us

The last command is unimportant, but may speed up the next few operations. The release notes again:

After running svnadmin upgrade, you may wish to also run the svn-populate-node-origins-index program on the repository. Subversion 1.5 maintains a node-origins index for each repository, and builds the index lazily as the information is needed. But for old repositories with lots of revisions, it’s better to create the index in one step, using the aforementioned tool, than to have live queries be slower until the index has built itself. See issue #3024 for details.

With my data safe and the repo upgraded, it’s time to actually test the new merge tracking features:

~/blog.bigsmoke.us # Enter working copy (on the same server)

# I'm now in the lichtgekruid branch.
svn switch file:///var/svn/blog.bigsmoke.us/trunk
svn ci -m "I was convinced this was a change which didn't belong to my feature branch" wp-content/plugins/openid

svn switch file:///var/svn/blog.bigsmoke.us/branches/lichtgekruid
svn merge file:///var/svn/blog.bigsmoke.us/trunk
# The last command was a real kicker, not having to find and specify the correct range of revision numbers.

svn ci -m "Merged changes from trunk to 'lichtgekruid' branch."
svn switch file:///var/svn/blog.bigsmoke.us/trunk
svn merge file:///var/svn/blog.bigsmoke.us/branches/lichtgekruid
# (Another spontaneous orgasm.)

svn ci -m "Merged 'lichtgekruid' branch back into trunk."

Ok, I know I could have simply changed all these projects to use Git, and I like Git. I love its simplicity and flexibility. But, call me old-fashioned; I have an SVN fetish, and so far I find its merge tracking quite convincing.

Besides all the gotchas and pointers in the 1.5 release notes, there’s a lot more info about merge tracking in the SVN redbook.

1. Comment by halfgaar
On January 30, 2010 at 12:32

Don’t you need to specify a path after switch and merge, like “.”?

Did you also get the log messages merged?

2. Comment by Rowan Rodrik
On January 30, 2010 at 16:10

You don’t need to specify a path after switch and merge, but what’s much more important is that you don’t need to specify a revision range. 🙂

I hadn’t checked about the merged log messages yet. I just tried it and at first was disappointed to see them missing, until I asked svn log for --help:

svn log --help|grep merge

-g [--use-merge-history] : use/display additional information from merge

With that flag added it works!

3. Comment by halfgaar
On January 30, 2010 at 21:03

I thought I had to specify a target path when I did a merge the other day… Oh well, don’t really remember.

As for the logs, I think it’s kind of weird that you have to explicitly ask for the merged history. Why would that be?

4. Comment by Rowan Rodrik
On January 31, 2010 at 19:06

I have the same sort of recollection about the target path for svn merge. I’m not sure if it was ever obligatory though. I vaguely remember that I once saw you omit it while I thought it necessary, but I can’t remember (not even vaguely) whether it would work that way at the time.

About the flag to show the merged history: this is what the release notes have to say about it:

The svn log and svn blame commands take a new -g (--use-merge-history) option, which tells them to take mergeinfo into account. Without this option, they won’t.

The reason for the -g option is that it is sometimes useful to ignore merge history. In blame output you sometimes want to see the person B who merged a change, though other times you want to see the person A who originally wrote the change that B later merged; use -g to get the latter information. In log output, you sometimes want to see exactly the revisions that were committed on a given line of development, though other times you want to see, as part of the same output, the original changes that were later ported as merge revisions; again, -g includes the latter information (tagged with lines that say “Merged via: ” followed by the revision number in which the merge took place). See Merge-Sensitive Logs and Annotations in the Subversion book for more details.

5. Comment by Rowan Rodrik
On January 31, 2010 at 19:10

I just learned that to remerge the branch into the trunk, I should have used the --reintegrate flag. Again from the release notes:

The --reintegrate option is used when merging a branch back to
trunk; it checks for some common safeguard conditions and then does
the merge in a fast and efficient way. See Keeping a branch in sync in the Subversion book for more.

6. Comment by halfgaar
On January 31, 2010 at 23:04

I tried merging the other day, and it failed because I didn’t specify a target path. If I recall correctly, I did “svn merge http://blablabla/branch/bla .” and the . was necessary.

I don’t really get the reintegrate flag BTW. If it knows the starting point of a branch (when trunk became branch), shouldn’t it know everything it needs to know?

7. Comment by Rowan Rodrik
On February 1, 2010 at 01:05

The need for the --reintegrate flag mystifies me too at the moment. 😕