I like to periodically shake-up the version control, re-align it with the way the project is going and clean up any clutter. As it was time to split one big project into several more-less separate tracks, I ran into an article announcing the release of version 1.0 of AnkhSVN, a free subversion plugin for Visual Studio. AnkhSVN had proper solution browser integration, and a ‘working copy explorer’, very much like the Eclipse synchronise screen. It looked very promising, so we decided to try it out.
I read a lot about Subversion, but never really had a reason to move from CVS – there was no new killer feature. We were generally satisfied with CVS, with just one problem. Integration with Visual Studio was virtually non existent. In January, several readers suggested trying out Subversion instead of CVS, and shortly after I took their advice. It turns out that the killer application, that made us move to Subversion, was the Visual Studio Plugin.
Migration from CVS
The migration from CVS was relatively easy. Subversion does edit-and-merge like CVS, works good over WAN lines, has proper GUI client tools for Windows and a command-line interface for easy scripting.
In terms of usage, two biggest differences from CVS for me were attributes and the branching system. In CVS, files are ignored just by adding their name to .cvsignore. Subversion does that with directory properties (use propset option from the command line). We migrated the repository quickly with a small shell-script that ran through the repository tree and loaded .cvsingnore into directory properties.
Branches and tags are just copies in Subversion. This makes branching somewhat simpler, as just a part of the repository can be copied (and branched), without affecting the rest. However, at first I had big reservations regarding tags as copies. With CVS, I used tags to mark a release or a significant starting point before a big change, so that I could easily go back. I thought that copying would just take too long and that it would take too much space. However, it turns out that copying in Subversion is not physical – a new branch or tag is created with a simple atomic operation that just sets up a link from the new location to the current version (from that point, of course, the copy can be modified independently).
Subversion also has automatic versioning of the complete repository, not just per file. Each commit operation is assigned a unique version number – this pretty much takes care of marking important savepoints, as we can go back and take the whole repository in a specific version. Although we could theoretically use these numbers to track releases, I still like to tag released files and give them a sensible descriptive name, instead of remembering that last iteration was 1182.
From the user perspective
Subversion has quite a few features not present in CVS. Most importantly, SVN does atomic commits (so the entire batch of related updates will fail or succeed), and can work natively over HTTP, so you instantly get a web-based interface just for browsing. Automatic versioning allows the system to keep track of which line was changed by whom in which revision, and that information is easily accessible as the ‘blame’ feature (maybe not the best name, but it makes a point). File renaming and moving are also versioned, so Subversion does not get in the way of refactoring.
In terms of client software, the Eclipse plugin for SVN looks and behaves very much like the CVS plugin (with a few added functions), but I did not see any major differences between them.
On Windows, we are using TortoiseSVN, a free plugin which provides access to the repository from the windows file explorer. It works very similar to TortoiseCVS, but has a few added functions for differences and merging.
AnhkSvn turned out to be a very interesting tool, providing direct integration with SVN from visual studio. In terms of features and performance, Tortoise seems better, so we tend to use both. AnhkSVN is good for files being developed in Visual studio, as it automatically adds new source files to the repository and gives us quick visual feedback of what was changed in the whole project tree. The only “problem�? I have run into is when it stops renaming files which were added but not yet committed. I occasionally change my mind about the class name (and file name) soon after a new file is created, and file renaming just silently dies when AnkhSVN is turned on. This was a bit frustrating at first, but once I realised what the problem is, it was not hard to work around it. All in all, very useful.
An important feature for us was also the integration with Cruise
Control.Net. Since version 1.2, CC.Net can automatically check out source folders from SVN (even the initial checkout, which is not available for CVS), and can tag successful builds.
From the admin perspective
SVN repository setup is straight-forward, like CVS, but there are quite a few options how to set up the whole system, so analyse them carefully if you are thinking about moving to subversion.
SVN does not have modules, like CVS, but allows the users to check out individual directories. Tags and branches complicate things a bit, because they are also accessed directly from the main file structure (they are just copies of files). With all this flexibility, it’s important to structure the repository so that people can check-out only relevant parts. This typically means that the top-repository level should be divided straight away into branches, releases, automated builds and the current working copy (called trunk in SVN language). We missed that one – and decided to structure the repository first by sub-projects and then do a division between source, branches and tags on the second level. It turned out that this made it hard to check out all related projects quickly. The next time we shake-up the repository, the first level will probably provide a division between trunk and copies, and projects will be on the second level.
SVN has two options for repository storage – individual files (similar to CVS) or an embedded database. Apparently, the first is a bit slower for access, but supports online backups and can be repaired easier in case of problems. We chose to use files, and (luckily) so far did not need to test the proposition that files can survive crasher easier. As for performance, it was quite good with files, so I don’t think that we will be moving to the database any time soon.
There are also several options for remote access. SVN has a binary protocol (which can work over SSH) and there is an Apache plugin which provides HTTP(S) support. Our version control server runs on Linux, and we decided to use Apache for several reasons:
- easier disk privilege management – entire repository is owned by a single user on server, access controls are handled by Apache
- new users can be added easier – they do not have to be system users, but are just defined in a httpd users file
- access control lists can be specified for a part of the hierarchy, and all ACL lists are in a single file, easy to control
- HTTP server automatically allows repository browsing
- Theoretically, having multiple users access the repository through a single funnel (in this case HTTP server) will reduce the chance of file corruption.
There are a few other advantages of working over HTTP like support for online GZip traffic compression. Again, the performance was quite satisfactory, both on the local network and on WAN lines. It would probably run faster with a binary protocol, but isolating under an Apache module makes the repository much easier to manage.
Although Apache module itself provides support for repository browsing, we also installed viewvc, a better Web-based interface which displays last modifications and provides basic support for checking differences online.
The story so far
So far, I am happy with Subversion and what it has done for us. The only real problem we encountered in these three months is bailing out after something was committed by mistake. With CVS, repairing the problem would be simply checking out a tagged revision, then committing over the repository again. SVN makes this quite hard because it remembers the revision you checked out, so it’s not easy to override the current version with an older one. So far, we had to deal with this situation three or four times, by copying the old revision to an external location, checking out the latest version, then copying files from the external location by hand. I guess that there is a better solution for this problem, but so far I did not find it.
As it has atomic commits, theoretically it should not be too hard to make Subversion roll back the last revision, and that functionality would make it, from my point of view, very close to an ideal version control system. I would certainly recommend evaluating it if you are shaking up the current version control, or starting a new project.
Image credits: Sick 31/SXC