Subversion Revision Control

SVN (Subversion), is a version control system. Normally when a file is saved only the state of the file is permanently recorded. SVN allows you to not only save the state of the file but also a history of all the changes made to that file.

This history of changes provides some important benefits when working with your files. Imagine that you are writing a huge program that is almost working perfectly. You add a few changes, they seem to work fine, and you keep working. A lot of changes later, you realize that the earlier changes did not work quite the way you intended. Now you need to fix them. Unless you have an exceptional memory and can recall all the minute additions you have made, fixing your changes is going to be a good deal of guess work. SVN takes out the guess work. It lets you query your files to discover what those changes were, and when they were made.

Another reason to use SVN is for group projects. SVN allows multiple people to edit files at the same time, and it intelligently merges the changes. This feature also helps you when you want to code on different machines without worrying about transferring the source code between machines manually. If used correctly, SVN also guarantees that you won't be using old versions of files.

Terminology

Though at first some of these terms may seem illogical, as we walk through some examples and you start using SVN they will make more sense.

Repository:

An SVN repository is the location where SVN stores all of the files that it tracks. Files in this directory should almost NEVER be accessed directly by the user.

Module:

A module is a directory inside the repository. A subversion repository usually consists of a few modules initially:

branches/
tags/
trunk/
Revision:

The revision number reflects the number of commits that have been made to the repository.

Trunk:

The trunk is a module of the repository, usually called "trunk", in which the main development happens.

Tag:

A tag is a snapshot of the repository's trunk, copied to its own module in the tags. This is usually used to keep a reference copy of your code, such as a release.

Branch:

A branch is a snapshot of the repository that is used for heavy development. This is so you won't break your working code while you add the next large feature.

HEAD:

HEAD most recent revision of a module.

Setup

Creating a Repository

You need to choose the directory where your repository will live. If you are using this for yourself, somewhere in your home directory would be fine. If you want to use it for a group project, you should put it in a group directory so your group members can commit and pull changes. This example will create a directory in ~ called svnroot:

cd ~
svnadmin create svnroot

The svnadmin utility will create a directory called svnroot, and put a bunch of things in there. Don't ever modify anything in there. SVN will take care of things for you. That directory not only stores the files, but it stores all the history too.

Checking Out

Now that you have a repository, you need to make a "working copy" of it. Remember how you aren't supposed to touch the svnroot directory? This is how you get started:

svn checkout ~/svnroot ~/myproject

This will make a checkout, or a "working copy", of your svnroot/ repository, and put it into a directory called myproject. If you change to the myproject directory, it should be empty, except for the .svn/ directory in there.

Adding the first files

Remember all that talk about trunk, tags, and branches? It is completely optional to use them. The suggested layout of your repository is to create three directories: branches/, tags/, trunk/. After creating these directories, you can put your project into trunk. If your brand new project only has one file, helloworld.cpp, just move it into the trunk directory. Now that your working copy has some folders and a file in it, you need to tell svn about it:

svn add branches tags trunk trunk/helloworld.cpp

Now svn knows about these files. Now, make your first commit:

svn commit . -m "initial import"

Note the -m argument. Keep it something short and sweet. This is the comment that is associated with your commit.

Common Commands

Now that you have a basic repository and a working copy, lets walk through a couple commands.

Pulling updates from the repository

If you are working with others, you need to be able to incorporate their changes and vice versa. Over the weekend you slept, but one of your group members went through and added comments to the code. He has committed his changes to the repository, so your working copy is now a revision (or more) behind the repository. To get caught up, you just run the following:

cd ~/myproject
svn update

The changes in the repository will be pulled down, and your working copy will now reflect the latest state of the repository.

Merging

If your group member made and committed his changes, and he changed a file that you were also making changes too, you will (possibly) end up with a conflict, and have to go in and merge your changes with his. SVN is smart enough to merge many cases, but if you both changed the same line to something different, it will be marked in your file, and you will need to fix it.

Working with Tags

After working on this code for some time it is likely we are going to have a version that we want to release or pass off. A nice feature of SVN is that we could create a tag. The way to do that with svn is with the svn copy command:

cd ~/myproject
svn copy ./trunk ./tags/passoff1
svn commit -m "This code was passed off for lab1"

Do not use the regular cp command. svn copy will keep the file history in tact, as well as keep track of a few other things.

Working with Branches/Merging

Branches are created like tags are, but instead of leaving the directory alone, you make changes:

cd ~/myproject
svn copy ./trunk ./branches/lab2changes
svn commit -m "I need to rework a lot of the code for lab2"

Now you can make changes to your code in the branch, and leave the trunk alone. This is mostly useful when there are several people using a working project stored in svn, but various people want to add big things to the project. If changes are made to the trunk while you are still developing on the branch, you can merge those changes from trunk to your branch:

cd ~/myproject
svn merge ./trunk ./branches/lab2changes
svn commit -m "updated my branch to trunk's head"

That is so when someone else fixes a typo in the comment, it will be fixed in your branch too. When your changes are complete to the branch, you merge them into trunk. This works almost the same:

cd ~/myproject
svn merge ./branches/lab2changes ./trunk
svn commit -m "merged the lab2changes branch to trunk."

Remote Access

If you want to work on your project at home, you could ssh in to the cs department and access your working directory that way, or you could make another checkout at home.

Remember when we created the repository, we created a working copy by doing:

svn checkout ~/svnroot ~/myproject

If you are on your home machine, you can check out your repository there too. This assumes you are running a unix-like environment at home, and you have ssh and svn installed. This should work on linux, mac os x, and even through cygwin on windows:

svn checkout svn+ssh://<username>@schizo.cs.byu.edu/users/<group>/<letter>/<username>/svnroot ./myproject

Note the /users/<group>/<letter>/<username>/svnroot should be replaced with the full path to your svn repository on a linux workstation. You can change to the directory and type pwd to get that information for you.

Learning More

This is a very brief introduction to SVN. There is so much more to learn. I highly recommend reading the svn book at http://svnbook.red-bean.com/.

Don't forget the svn homepage, http://subversion.tigris.org/. Also take a look at the svn manpage.