You are here: Home Service Subversion Best Practices

Subversion Best Practices

This is a quick set of guidelines for making the best use of Subversion in your day-to-day software development work. For more information about Subversion, its concepts or commands please refer to the Subversion book.

 

Use a sane repository layout

There are many ways to lay out your repository. Because branches and tags are ordinary directories, you'll need to account for them in your repository structure. The Subversion project officially recommends the idea of a "project root", which represents an anchoring point for a project. A "project root" contains exactly three subdirectories: /trunk, /branches, and /tags. A repository may contain only one project root, or it may contain a number of them.

 

Commit logical changesets

When you commit a change to the repository, make sure your change reflects a single purpose: the fixing of a specific bug, the addition of a new feature, or some particular task. Your commit will create a new revision number which can forever be used as a "name" for the change. You can mention this revision number in bug databases, or use it as an argument to svn merge should you want to undo the change or port it to another branch.

 

Use the issue-tracker wisely

Try to create as many two-way links between Subversion changesets and your issue-tracking database as possible. If possible, refer to a specific issue ID in every commit log message.When appending information to an issue (to describe progress, or to close the issue) name the revision number(s) responsible for the change.

 

Understand mixed-revision working copies

Your working copy's directories and files can be at different "working" revisions: this is a deliberate feature which allows you to mix and match older versions of things with newer ones. But there are few facts you must be aware of:

  1. After every svn commit, your working copy has mixed revisions. The things you just committed are now at the HEAD revision, and everything else is at an older revision.

  2. Certain commits are disallowed: the deletion of a file or directory which doesn't have a working revision of HEAD or the property change to a directory which doesn't have a working revision of HEAD.

  3. svn update will bring your entire working copy to one working revision, and is the typical solution to the problems mentioned in point #2

 

Know when to create branches

This is a hotly debated question, and it really depends on the culture of your software project. Rather than prescribe a universal policy, we'll describe three common ones here.

With the Never-Branch system users commit their day-to-day work on /trunk. Occasionally /trunk "breaks" (e.g. doesn't compile) when a user begins to commit a series of complicated changes. This is a very easy policy to follow and new developers have low barrier to entry. Nobody needs to learn how to branch or merge, but this may lead to chaotic development and the code could be unstable at any time. Because Subverion commits are atomic this sort of development is a bit less risky in Subversion than in CVS.

With the Always-Branch system each user creates/works on a private branch for every coding task. When coding is complete, someone (e.g. coder or manager) reviews all private branch changes and merges them to /trunk. The code in /trunk is guaranteed to be extremely stable at all times. The coders are artificially isolated from each other, possibly creating more merge conflicts than necessary. This also requires users to do lots of extra merging.

With the Branch-When-Needed system users commit their day-to-day work on /trunk according to some simple rules. Then the code in /trunk is guaranteed to be stable at all times and the hassle of branching/merging is somewhat rare but the. But it adds a bit of burden to users' daily work: they must compile and test before every commit.

  1. /trunk must compile and pass regression tests at all times. Committers who violate this rule are publically humiliated.

  2. a single commit (changeset) must not be so large so as to discourage peer-review.

  3. if rules 1. and 2. come into conflict (i.e. a series of small commits would disrupt the trunk), then the user should create a branch and commit a series of smaller changesets. This allows peer-review without disrupting the stability of /trunk.

 

Select a versioning scheme

Depending on the type of project choose a simple and also flexible and scalable version structure. The version labels are equal to the idenitifiers used for new branches or tags. Branches are used to try out new feature without disturbing the main line of development. And as the new feature becomes stable the development branch is merged back into the main branch. Tagging is to mark particular revisions (e.g. release version), so that you can recreate a certain build or environment at any time. Tags are used to create a static snapshot of the project at a particular stage.

Subversion itself makes no distinction between tags and branches, but they are there for different purpose. Tags are not normally used for development, Branches must be used for that purpose. So working on a tag revision is not a good idea. So you must remember this as there is nothing to stop you doing this by mistake.

Branching or Tagging done by Subversion are just internal links (cheap copies) pointing to a specific tree/revision and thus can be created very quickly and also take up almost no extra space in the repository. If you modify a working copy created from a branch and commit, then all changes go to the new branch and not to the trunk. Only the modifications are stored and the rest remains a cheap copy.

Many times it may happen that you need to make further changes to a release which has been already tagged. The correct way to handle this is to create a new branch from the tag first and commit the branch. Make Changes on this branch and tag the branch for every build with increment in the revision number.

The version labels should at least consist of a major and a minor version number and may include a build and a revision number (e.g. "v1.02.101231.123"). A new major releases introduces new (major) technologies and changes that render previous production releases obsolete. A new minor release depict feature level enhancements. Addition of features between releases result in incremented minor release. The build number is sometimes an auto-generated number, assigned for each (successful) build on a day basis using YYMMDD format, The revision number is reset to zero, for each new major/minor version released. For all later bug-fixes, patches to releases that reach production, this number shall sequentially increment.

 

References