1. Introduction
Subversion [1] can be used in many different ways which are described in Subversion's Red Book [2]. For example, Chapter 4 (Branching and Merging) of the Red Book describes how Subversion can be used to manage the releases of different versions of a collection of files.
When doing this, Subversion uses the following terminology:
- trunk
- This is a directory containing the collection of files. Any edits to the files should be performed on the files in this directory.
- branches
- This is a directory that has subdirectories. Each subdirectory contains a variant of the collection of files in the trunk directory. The branches directory is useful when people want to work on their changes in an independent fashion. Each person copies the files from the trunk directory to a separate subdirectory of the branches subdirectory. The Red Book describes some of the issues that are involved when you later wish to merge these branches. This is an area where Subversion acknowledges itself as being deficient.
- tags
- This is a directory that has subdirectories. Each subdirectory contains the collection of files that existed in the trunk directory at some point in time. When you want to release a new version of the collection of files, the files can be stored in a new subdirectory of the tags directory.
I have not yet explored the creation of branches. So the rest of these notes are about how the tags directory can be used.
Although Subversion's Red Book documents how to use the commands for creating tags (and branches), these commands can easily be misused: there are no safeguards built in to ensure that they are used appropriately.
So, in my view, Subversion works at too low a level. It does not force a work practice on me. These notes explain how I use combinations of these low level commands and how this has led me to produce scripts (that effectively work at a higher level).
2. Creating the initial tag
If you are wanting to do some work on a piece of software, there will already be a collection of files. It it likely to be in a tarball called:
$productname-$productversion.tar.gz
First go to the appropriate place in your working copy of the Subversion repository, e.g.;
cd $HOME/svn/projects
And then create a new directory for this project:
mkdir $productname
And, in this directory, create empty subdirectories called branches and tags (although the branches subdirectory will not be used):
cd $productname
mkdir branches tags
And then unzip the tarball:
tar zxf ~/$productname-$productversion.tar.gz
If this has been created 'properly', the untarring will produce a subdirectory called:
$productname-$productversion
So change its name:
mv $productname-$productversion trunk
This has created the initial collection of files.
We can transfer these files to Subversion repository using:
cd ..
svn add $productname
svn -m "trunk contains original and branches and tags are empty" \
commit $productname
cd $productname
We can also make a copy of the original files in the tag directory:
url=https://svn.oucs.ox.ac.uk/projects
svn copy $url/$productname/trunk \
$url/$productname/tags/upstream-$productname-$productversion \
-m "original source"
We can then ensure that our working copy has a copy of this new version of the tags directory:
svn update tags
3. Changing the files
If we want to change the collection of files, we move to the trunk directory and edit those files:
cd trunk
use favourite editor on the files in this directory
When we want to ensure that the Subversion repository has the latest version, we can do:
cd ..
svn --force -q add trunk
svn -m "some appropriate message" commit trunk
Note: the first of these svn commands recursively descends the trunk subdirectory adding any new files to the working copy.
After the svn commit command, the files will be available at:
https://svn.oucs.ox.ac.uk/projects/$productname/trunk/
4. Releasing a new version
At some stage, when we are happy with the files in the trunk directory, we will want to release them as a new version. This can be done as follows.
First get to the right directory, e.g.:
cd $HOME/svn/projects
cd $productname
Then ensure that there is an up-to-date copy of the files of the trunk subdirectory in the Subversion repository:
svn --force -q add trunk
svn -m "some appropriate message" commit trunk
Then create a new tags subdirectory in the Subversion repository:
svn copy $url/$productname/trunk \
$url/$productname/tags/$version \
-m "$version: some appropriate message"
This command assumes that $version has been set to some appropriate string. I use:
version=$productversion-$oxversion.ox.1
where $oxversion is increased by 1 at each release.
Finally, ensure that our working copy has the latest version of the tags subdirectory:
svn update tags
These files are now available at:
https://svn.oucs.ox.ac.uk/projects/$productname/tags/$version/
5. Introducing new commands
I think it is tricky to get all the above commands right. So, in order to ensure that I do, I have created two shell scripts:
mkmrbsinit
mkmbrstag
mkmrbsinit has contents similar to the following:
oxversion=1
productname=mrbs
productversion=1.2.3
url=https://svn.oucs.ox.ac.uk/projects
cd $HOME/svn/projects
mkdir $productname
cd $productname
mkdir branches tags
tar zxf ~/$productname-$productversion.tar.gz
mv $productname-$productversion trunk
cd ..
svn add $productname
svn -m "trunk contains original and branches and tags are empty" \
commit $productname
cd $productname
svn copy $url/$productname/trunk \
$url/$productname/tags/upstream-$productname-$productversion \
-m "original source"
svn update tags
mkmrbstag has contents similar to the following:
oxversion=$1
shift
message="$*"
productname=mrbs
productversion=1.2.3
url=https://svn.oucs.ox.ac.uk/projects
version=$productversion-$oxversion.ox.1
cd $HOME/svn/projects
cd $productname
svn --force -q add trunk
svn -m "$message" commit trunk
svn copy $url/$productname/trunk \
$url/$productname/tags/$version \
-m "$version: $message"
svn update tags
I use them like this:
mkmrbsinit cd $HOME/svn/projects/mrbs/trunk patch --no-backup-if-mismatch <$HOME/mrbs/patches/2.patch mkmrbstag 2 add changes made by sysdev to the previous system patch --no-backup-if-mismatch <$HOME/mrbs/patches/3.patch mkmrbstag 3 fix bug in SQL when repeat table is empty
6. Building from scratch
As you can see from the above, I have stored the changes from one version of the files to the next in a patch file. As shown above, this allows the latest version to be built by starting from the original source and then applying the patches in turn.
A patch file is produced by doing something like:
diff -x '.svn' -Naur tags/$productversion-2.ox.1 \
tags/$productversion-3.ox.1 \
>$HOME/mrbs/patches/3.patch
7. References
Subversion http://subversion.tigris.org/
Subversion's Red Book http://svnbook.red-bean.com/
8. Comments
Those are my (BarryCornelius) thoughts about the use of tags in Subversion. Please add your comments about this below. Thanks.

