The company I work for has been using subversion for several years now and it suits our needs reasonably well. It’s generally pretty easy to use; it’s certainly an improvement on CVS, but on the other hand there are some things that aren’t all that great. The way externals were implemented leaves much room for improvement and svn tends not to play nicely with mixed user permissions (such as when files are written alongside or over checked-out code by www-data). Subversion has a relationship with posix ACLs that is rather less cordial than the one described in The Pogues’ Fairytale of New York, but these are perhaps war stories for another time. These errors at least have the decency to fail with the requisite amount of melodrama.
More recently we’ve come across some more subtle and potentially nasty issues that subversion barely bothers to notify you about, if at all.
The way our shop works, we have a single trunk from which branches are forked. Changes are made on-branch before being tested and re-integrated into the trunk. Problems can arise when you make changes to a file on one branch (A), and move the same file on another (B).
Subversion treats moving files as a ‘delete’ and an ‘add’ (delete the old file, add a new file with the same contents and a different name). If you integrate branch A and then branch B, the newer changes from branch A will be lost (as the file is deleted) and the branch B version will be instated with its new name. SVN does not warn you that a newer instance has been overwritten – charming.
If on the other hand, you merge branch B first, then branch A, then because subversion can’t find the the file to merge with branch A (because it was renamed in B), it simply reports that the file is ‘skipped’. No mention that changes to that file could not be merged as the file was not found just ‘skipped <filename>’.
Easy enough to miss when you have several hundred files scrolling past you at a rapid rate of knots.
Apparently, the best you can do is be very, very careful when integrating branches that contain deleted or renamed files. I’ve taken to pointing any sizeable svn output to a file and grepping the hell out of it.
A similar thing happens when you use nested branches. This one is perhaps more understandable, but the level of reporting is just as woeful. If you branch from the trunk, then make a second branch from the branch then care must be taken if you attempt to merge the second tier branch directly back to the trunk. If you have added files in the second tier branch, they too will simply be ‘skipped’ if you attempt such a merge.
Merging back to the first tier branch is no problem, and is probably what the system was designed for. We discovered this issue when a developer created the nested branch to make newer updates to a very old branch. A better solution would have been to create a fresh branch from the trunk and merge the changes from the old branch into it, before making the required modifications.
Hopefully these are useful to some of you other SVN users out there.