thinking in geek tagline’s are so web2.0

Posted
6 August 2007 @ 6pm

Tagged
scm

On merging (svnmerge.py)

This subject has come up a few times in the last few days - I thought I’d take the opportunity to collect my thoughts from various emails and put them here.

Svnmerge.py is a tool which tries to fix the _totally broken_ “svn merge” command.  Here’s an example scenario. My repository contains a number of branches of the same product:

/trunk - the main line of development. New features are added here.
/branches/Customer1 - We made a release to a customer - this is the version that was released.
/branches/Customer2 - Another release for a different customer.

/trunk, /Customer1 and /Customer2 all contain bug fixes fixing critical bugs which were discovered in production by different customers. In an ideal world we would be able to get our SCM to list all the changes to Customer1 and choose which ones to apply to /trunk and Customer2. Subversion lets you do this using the merge command.

svn merge /branches/Customer1 /trunk

What this does is take all the changes to Customer1 which have been made since the branching of Customer1 from trunk and apply them to trunk. The first time this works great. All the changes get made to my working copy and I can go through an commit them and every things groovy.

The next day I have (another) critical bug for Customer1. I fix it - and commit my change to the Customer1 branch. Then I need to merge again.

svn merge /branches/Customer1 /trunk

What this does is take all the changes to Customer1 which have been made since the branching of Customer1 from trunk and apply them to trunk. Can you see the problem here? If you can’t let me explain. It will attempt to apply the same changes it applied previously, this will generate conflicts, potentially _lots_ of conflicts. They will need to be manually resolved and then just the new (bug fix) changes committed.

Until next time when svn merge will - take all the changes to Customer1 which have been made since the branching of Customer1 from trunk and apply them to trunk. ARRG. See what I meant by brain dead?

It actually gets worse. I also want to merge bug fixes from /Customer2 -> /trunk and from Customer1 -> Customer2 and Customer2 -> Customer1. Not to mention the bugs you find while doing development and fix in the trunk that should be merged back to the customer branches. /trunk -> /Customer1 and /trunk -> /Customer2.  This is a boat load of manually fixing up conflicts that needs to happen. Every time. It’s almost easier to manually change the necessary files for each branch.

In all honnesty - I wouldn’t try to merge bug fixes from the trunk to branches - if I found a bug in dev - I’d chose a customer branch to fix it in and merge it into the trunk from there. Anything else would be too painful.

How does svnmerge.py help? What svnmerge.py does is store some metadata in your repository (actually - per branch - which is part of the problem) about which revisions you’ve previously merged. This way - when you use svnmerge - it will only apply changes to your working copy that have not been previously merged.

Yay - problem solved right? Unfortunately - no. There’s a problem. If you only ever have two branches - then this will work pretty well. If you have more than two then your stuffed. e.g. /trunk /branches/Customer1 /branches/Customer2 = 3 = bad news.

The reason is that  svnmerge tracks merges per branch - it doesn’t support what the svnmerge guys call graph based merges. A graph based merge looks like the following:

e.g. /Customer1 <->  /Customer2 <-> /trunk <-> /Customer1 (this scenario is described above when merging bugfixes from the trunk to branches).

You have to setup bidirectional merging on each branch.

/branches/Customer1 <-> /trunk
/branches/Customer2 <-> /trunk
/branches/Customer2 <-> /branches/Customer1

If I merge my fixes from /Customer1 -> trunk then /Customer2 knows nothing about it. When I try and merge all three branches I end up getting conflicts. The problem is that the history is lost when you merge a bugfix Customer1 -> trunk -> Customer2 - svnmerge only knows change in Customer2 came from the trunk - not from Customer1. If that change was previously merged Customer1->Customer2 (critical bug for example) then you’ll get conflicts again.


1 Comment

Posted by
Richard
19 September 2007 @ 7am

Have you looked at http://www.bestpractical.com? They have SVK, which is a perl layer on top of the SVN API that allows for more intelligent merging (including support for star-merge).


Leave a Comment

SoC in WebForms Business Intelligence in Business Apps