Good practice Branching and Tagging with version control

Tuesday, 20 October 2009

In this tutorial I will go over my preferred method for branching, tagging and comitting. I will steer away from calling this best practice as there are other ways to do this, but I will go so far as to say this is a clean method that works and ensures you can easily keep control of your different working versions, easily reintegrate changes from different paths and restore previous versions for testing / fixing. Which should be your aim for tagging and branching.

If you like to discuss, there are several reasonable discussion going on at Stack Overflow. If you are interested here, here and here.

If you are using subversion to manage your version control and you haven't done so yet, take the time to read the book.

Let's start by going over some common definitions that I'll be using throught the tutorial:

Trunk - this is where your main version of your application will be held; any maintstream development will take place on the trunk version of your application

Branch - a branch is a work-in-progress version of your application and will be for fixing a particular release or for developing new features which may or may not be reintegrated into the trunk at a later stage

Tag - start by thinking that a tag is a version that will never be altered again; it is like a piece of boxed software that has already hit the shelves, if you want to make changes, you will need to call it something else, if it was 7.0.1 you will might call the work in progress the 7.0.2 version

Commit - saving a version of your changes to the repository

Merge / merging - taking the changes from one version of your application and moving it to another version

I will begin with our trunk. If you have been using a version control system, but haven't been branching or tagging you will have a good idea of how the trunk works. For any simple system the whole repository is used as the trunk and will look like this:

* Repository is created.
* Files are committed in and out of repository by individuals and are worked on
* Changes are then committed back to the repository
* Any new development that may cause issues is not committed until it has been tested then it is committed to the repository
* A release is made simply by checking out a version of the repository at a point in time when the team is happy that it is stable
* Any further tweeks made before a full release are made to the repository and the version for release is just updated

This is a pretty standard workflow for many smaller teams and will give you a good idea of what our trunk will look like. As development goes along our trunk continues to grow in a straight line; the repository is rarely reverted and past changes are not reflected on, just modified. The trunk contains all of our changes and just keeps going up and up.

This is a perfectly fine way to operate, but let's go over some of the benefits of being able to tag and branch:
* By branching we can multiple versions of the system being worked on that can either be abandoned or reintegrated at any point. The beauty of this is that any changes made don't need to be held back from being committed and won't infect the trunk with untested / unstable code. Think of smaller part of your team having to work on a new feature that will take over 3 months; having them not commit for that time will mean they will need to work outside of the repository and will be difficult to integrate changes.
* By branching we can easily reintegrate individual commits to the branch back in to the trunk as they are tested
* By tagging we know exactly what is in a release that has been passed on to a customer or is on your production server currently. No more guessing as to which commits went in to production last month.
* By tagging we can easily retrieve a tagged version from the repository for testing purposes
* By tagging you can retrieve the tagged version, make changes just to that tag and then create a new tag. Think of this, your production 7.5.1 version has an issue that you only just found and your team has already made 100+ commits to the trunk in that time. Rather than making the changes on the live version, you just grab the 7.5.1 tagged version, make your changes to it, create a tagged version and move the new version to production. There will no longer be any chance of new changes being moved to production without testing.

Be aware that by using branching and tagging, each branch or tag is like a mini-repository, you can check-out and commit to you branches and tags as well as your trunk.

We'll now look at branching. Branches are work-in-progess versions of your application. There are a few different reasons that you may want to branch;
1. You want to start developing some new functionality that may or may not be integrated into the trunk at a later stage.
2. You are getting ready for a release, but you may still have some final non-major changes to be made.
3. You want to start working on a version based on a previous tag because you have discovered an issue with that tag, but the trunk has already progressed past that tag.

With each of the scenarios above there is a particular workflow. The generic workflow is as follows:
* Create a branch by copying a particular revision of your application; either by copying a tagged version or by taking the latest version of your repository.
* Make changes to your branch and commit until you are finished.
* Tag your branch for any future operations and then remove your branch so that nobody else continues to perform work on it
* Reintegrate the changes to your branch back in to your trunk if necessary

Now let's have a look at home we can apply our workflow to each of our branching scenarios above:
* Create a branch by copying the trunk
* Develop the new functionality
* Tag the version with new functionality
* Add the new functionality to the trunk if necessary by merging changes from the tagged version to the trunk
* Create a branch by copying the trunk
* Test the branch as though it were the release version
* If there are any changes make these to the branch and merge back to the trunk as necessary
* When there are no further changes to be made create a tagged version and then remove the branch
* Move the tagged version to production server
* Create a branch based upon the tag with a bug in it
* Make the fix on the branch and merge the change into the trunk if necessary
* Create a tagged version of the branch and remove the branch
* Move the tagged version in to production (if necessary)

You should now be able to see the benefit of branching and tagging. Your production version is protected from accidental changes and your working trunk version is developed independantly and alongside any major changes.

Your version control software should have features to allow for branching and tagging and to easily merge changes. I prefer to use subversion with TortoiseSVN client as the above operations are done with a few clicks.

The best way to structure your folders for branching and tagging should be similar to the follow to alow you to easily view your versions:

..trunk files

I also recommend you use a visual repository browser so that you can easily view changes and commit mesasges to each of your versions. We are using websvn
blog comments powered by Disqus