Archive for the ‘Software Development’ Category

Keeping track of merges in SVN 1.5

Sunday, May 17th, 2009

I’ve finally migrated to Subversion 1.5 hoping to be completely wowed by the new merge tracking features.  While they may be great on paper, the Subversive/SVNKit connectors that come with Eclipse (rather, Zend Studio for Eclipse) are less than exciting.  If you’re expecting, “wow, new interface and features”, don’t be, it’s a mild change at best.  However, the merge tracking definitely works and it works automagically.  The issue that I’ve run into with it is that while it may track what has been merged where just fine, someone still has to track all the things have haven’t been merged.  This especially true if you have a “stable” branch in your code.  As you bring features and updates from the trunk into that branch, SVN will happily track the revision numbers that you’ve merged.  But, what about all those ones that haven’t been merged yet?

Up until today, I’ve been going through a tedious process of reading the svn:mergeinfo field and comparing that against the commit logs from WebSVN or Fisheye, and then using the “whiteboard” method to keep tracking of that still needs to be looked at.  To solve this problem, I wrote a quickie PHP script that will read the svn:mergeinfo property as well as another property I’ve created called “minmerge” and spit out a list of revisions to look over.  The minmerge property is basically a number I set by hand that denotes how far back in to look.  Anything lower than that revision number is assumed to have already been processed and either merged or decided not to be merged.

<?
$mergedcmd = "svnlook pg /svn/testrepo svn:mergeinfo /branches/stable";
$minmergecmd = "svnlook pg /svn/testrepo minmerge /branches/stable";
$mergemsgcmd = "";
$merged = exec($mergedcmd);
$minmerge = exec($minmergecmd);
 
$merged = str_replace("/trunk:", "", $merged);
 
$revs = explode(",", $merged);
 
echo "found " . count($revs) . " merges \n";
 
foreach ($revs as $rev)
{
	if (strpos($rev, '-'))
	{
		$bounds = explode("-", $rev);
		for ($c = $bounds[0]; $c &lt;= $bounds[1]; $c++)
		{
			$realrevs[] = $c;
		}
	} else {
		$realrevs[] = $rev;
	}
}
sort($realrevs);
 
$min = min($realrevs);
$max = max($realrevs);
echo "found " . count($realrevs) . " revisions from $min to $max\n";
echo "ignoring revs above $minmerge\n";
 
for ($c = $min; $c &lt;= $max; $c++)
{
	if (!in_array($c, $realrevs) &amp;&amp; $c &gt; $minmerge)
	{
		$unmerged[] = $c;
	}
}
 
sort($unmerged);
echo "found " . count($unmerged) . " unmerged revisions:\n";
foreach ($unmerged as $rev)
{
	echo "$rev\n";
}
?>