CS360 Subversion Guide
CS360 Homepage

This is a simple Subversion tutorial created by Colin Mollenhour for CS360 course. updated on August 22, 2011

Skip to Lab Submission info

Table of Contents:

Background

Subversion (a.k.a. SVN) is one of the most widely used open-source version control systems available today. It builds on top of older systems, namely CVS and RCS, and preceeds the more advanced Distributed VCS packages such as Git (by Linus Torvalds himself), Bazaar (by Canonical, makers of Ubuntu), Mercurial, and others both open-source and commercial (e.g. BitKeeper, Microsoft Visual SourceSafe). Despite all of the differences in implementation, these systems all work off of the same principles of "diff" and "patch", two basic tools that you may already be familiar with that compare files line-by-line and use a standard format to describe and merge differences. Subversion can be used on a local filesystem or over a network and is based on a centralized repository architecture where users check out the repository to a local working copy, make changes, then commit them back to the repository. If necessary, merges with other revisions are carried out in a local working copy before they are committed.

Tutorial

The Subversion executables, svn and svnadmin for our purposes, are already available on the linux-based EECS machines. Subversion breaks the rules of using manpage documentation in favor of built-in documentation, so just type svn help or svnadmin help if you need further details or want to explore the other features.

For this class we are all going to share one repository with private directories for each student. To start using it, you will want to checkout a local copy. A local copy (working copy) allows you to make any changes you like without affecting the repository until you actually commit your changes. At any time, you can revert your code to the latest revision, or even back to any previous revision. More about this later... The svn client supports accessing a repository through multiple protocols, but we will be using https. You can checkout the repository from any computer that has a Subversion client installed like so:

> svn checkout https://web.eecs.utk.edu/courses/fall2011/cs360svn/$USER cs360
Checked out revision 0.

This repository requires authentication and is setup to use your EECS username and password. The "checkout" command will create a directory in your current working directory named cs360. This folder will contain a single folder named .svn (which is hidden by ls) that contains information about your working copy and the repository and should not be modified or deleted.

Now let's do something with our repository. I have written a clever little program that strangely segfaults.. You can download it here: http://www.cs.utk.edu/~cs360/genius.c, or I recommend saving it in your working copy directory by changing to that directory and using wget. However, before we start we will create a "test" directory as our sandbox and add it to the repository. All files that you want to be checked into the repository for version control need to be added using the svn add <file> command. This includes directories, README, makefile and any test case files. All contents of directories are added by default when the directory is added, but if you have files such as executables that are not to be checked in, this might not be what you want. If you add a file accidentally you can use svn revert <file> to un-add it.

> cd cs360
> mkdir test
> svn add test
> cd test
> wget http://www.cs.utk.edu/~cs360/genius.c

You can compile the test program and run it with gcc genius.c && a.out and you will get a segfault. Ok, before we start working on the file let's get it checked in.

> svn add genius.c

Let's see what we have so far:

> svn status
?      a.out
A      .
A      genius.c

This shows that a.out is not under verison control (?) and the current directory (.) and genius.c are scheduled to be added (A). So far the actual repository has not been modified, just your local copy. So, let's commit.

> svn commit -m 'Adding test and genius.c, the smartest program evar!'
Adding         test
Adding         test/genius.c
Transmitting file data .
Committed revision 1.

The -m option specifies a log message to go with the commit. You should always add a brief summary of what you are committing in this log message. Without the -m option, your $EDITOR will be opened for you to type a log message into, and upon a save and exit, the message typed will be sent with your commit. Now, let's fix that segfault.

Ok, looks like we made a CS102 mistake, doh! Let's fix that memory reference. After we're done, let's see what we have.

> svn status
?      a.out
M      genius.c

You can see that genius.c now has an M next to it because it is a file that already exists in the repository, but it has been modified from the latest version in our working copy. Notice the a.out still has a '?' next to it because we never added it, and we should never add it because we only use version control for source code. The TAs will be very disturbed if you've gone and checked in all of your .o files and executables, so please don't do it. If you are OCD about those question marks, then you can tell svn to ignore the a.out file (and for example all .o files while we're at it) like so:

> svn propset svn:ignore "a.out <press enter to create a newline>
*.o" .

Here we are setting the svn:ignore property, giving it a value of a.out<newline>*.o and setting the property on the current directory. From now on, svn commands will ignore those files in this directory. The next commit will set this property in the actual repository, so any checkouts will get this change when updated. There are many other properties that you can set but they will not be covered here.

Ok, let's test our program again with gcc genius.c && a.out and now that it works, let's review what we've changed:

> svn diff

Property changes on: .
___________________________________________________________________
Name: svn:ignore
   + a.out
*.o


Index: genius.c
===================================================================
--- genius.c	(revision 1)
+++ genius.c	(working copy)
@@ -1,6 +1,6 @@
 void main(){
 	int i;
 	printf("Enter a number and see how smart I am:\n");
-	scanf("%d",i);
+	scanf("%d", &i);
 	printf("2 + %d = %d....  Genius!!\n", i, 2+i);
 }

This command uses the diff tool (similar to diff -u) to compare our working copy with the checkout's latest revision. Under certain circumstances, such as when working from multiple locations or with multiple people, your working copy can become out of date. To update it, you simply run svn update. You can also compare your working copy or any revision with any other revision by using the additional command line arguments with svn diff. See svn help diff for more info.

You can see above that line 4 has been changed (- for old lines, + for new lines). What is nice is that svn diff operates recursively so it will output the diff for all scheduled changes including added or removed files and directories, changed properties etc... You can pipe this output to "less" if you just want to scroll through it, or output it to a file to essentially create a patch! This is useful if you aren't the repository owner or don't have commit privileges and want to send the owner a patch that they can view, or apply and commit themselves.

Create a patch:
> svn diff > my_patch.diff

Ok, let's commit the fix:

> svn commit -m 'Fixed segfault and added svn:ignore property'
Sending        .
Sending        genius.c
Transmitting file data .
Committed revision 2.

If you want to see the history for the repository (or a specific file or subdirectory) you can use the svn log command. You should refer to revision numbers in your log messages (e.g. "Reverting regression in r32") and in communication (e.g. "I fixed that bug in r35").

How often and when you should commit depends on the environment. For the lab assignments you are working alone, so in theory might never need to commit your work, but you are encouraged to commit at least every day you work on the assignment, or every time you reach a milestone, or whenever you are about to make changes you may want to undo or review later. We have not set a minimum commit policy in hopes that you will take our advice and commit often, but if we do not see widespread use of the svn repositories we may reconsider.

Other Information

Lab Submission

This semester, we are replacing the submit script with these subversion repositories primarily for your benefit. Being comfortable with Subversion is a valuable experience; you do not want to interview for a job and have zero experience with a VCS. It also makes the job of the TAs easier; we can simply checkout each student's repository and view the log to see the exact date and time it was committed. If you want to take a late lab or for whatever reason have some special circumstance where you need to give the TA your code after they have already checked out the latest code, that is fine, just notify the TA that you intend to make additional commits and notify them as soon as you are ready to turn it in. There will be absolutely no excuses for deleting code, introducing a bug last minute that now you can't fix, lost emails, etc. since all of these problems are solved with the use of Subversion. Also, if you were to run into some problem, the lack of any commits prior would not help you make a case that you've been working hard on your lab for the past week, so keep those commits rolling as you progress!

Starting a new lab:

Each assignment should be placed in its own directory named labX for lab assignments and hwX for homework assignments that involve code. Here is how you create those directories in the root of your repository:

> cd cs360      (this is the directory that was created by your first 'svn checkout' command at the beginning of this tutorial)
> mkdir lab1
> svn add lab1
> cd lab1
> <start creating and adding files>
> svn add <new files>
> svn commit -m "Adding lab1 directory and files"

Remote Access

You can easily access your repository from any computer with internet access, allowing you to, for example, check out and work on your code from home if you must go offline (otherwise I recommend simply using SSH to access your home directory live), commit it, go to the labs and checkout/update it, commit it, go back home, update, etc...

Conflicts When Updating

Don't forget to get your local copy up to date when switching locations by committing before you leave, and updating before you start (with a simple svn update). If you happen to have an outdated checkout and you edit the same lines that have already been updated in the repository, then you will get some conflicts when you svn update and you will be unable to commit without resolving them. Conflicts are denoted by a 'C' in the status column. Don't panic, just open the file and look for lines that look like this:

<<<<<<< .mine
  scanf("%d", &i); // get a number from stdin
=======
  scanf("%d", &i);
>>>>>>> .r2

The first line here shows where my local copy block that conflicted starts (.mine), then the '======' separates the blocks, then the last line shows where the revision from the update ends. In this case, my local copy was out of date (at r1), the "head" revision (in this case r2) had a conflict with my local working copy (mine). You will notice that some extra files are created with these extensions, so if you are positive that a certain revision has all of the right lines, you can copy that one over the original to get rid of the conflict markers, then run svn resolved when all of the conflicts are resolved. Only run this when there are no more conflict markers in the file with the original name. The extra files that were created will be deleted. There are some great GUI editors for viewing diffs and merging conflicts. tkdiff and vimdiff are the only additional tools I know of on the EECS machines, but there may be others.

Microsoft Windows and other platforms

If you are a Windows user, don't think for a second you are getting the short end of the stick here. In fact, Windows has available one of the best subversion clients in existence. See Tortoise SVN. It integrates right into explorer complete with icon overlays, context menus with all of the svn commands, and even great diff and merge tools! If you are a command line junkie and use windows, you can still download the original tools here for any platform, or install via cygwin if you are already using that. Also, most good IDEs these days have versioning support such as Netbeans and Eclipse built right into the editor.

Reverting Changes

If you need to revert the changes you made since the last commit, simply type svn revert. This will revert all uncommitted changes in the current directory (-R will do it recursively). You can revert only specific files by simply passing them on the command line.

If you need to go back to an older revision (revert changes that were committed), you will actually use the update command with the -r option. This will not only revert changes to files, but also added or deleted files. For example, to go back to revision 2:

svn update -r 2

Copying (Branching)

In Subversion there is a thing called "branching" that is most often used to work on a part of a project for some considerable amount of time and commit changes without affecting the main "trunk" of the repository. The project is organized with three directories, branches, tags, and trunk. Trunk is typically the most up-to-date but stable of the three. Tags contains "tagged" revisions (e.g. 1.0, 1.1, etc), and branches contains various works-in-progress or spin-offs. Even for large projects, it is not inefficient to keep all of these copies in the repository because they are soft copies, that is only the differences between them use any considerable amount of additional space. The "branches" are typically "merged" back into the "trunk" when a feature or major change is complete, then the trunk is tagged for a public release. There are variations on the uses of these of course, but they all use the svn copy command to create a copy of a versioned directory. For your purposes, you *may* find it useful to create a copy of an older lab or homework if the new one is going to be particularly similar to the old one, saving you the hassle of re-adding the same files anyway, and allowing you to track your changes back past the old version, without losing your easy access to the old version in it's own location. Example (copy hw1 to hw2 and schedule for addition):

> svn copy hw1 hw2

Using Subversion Outside of CS360

As you are hopefully realizing now, svn can be a very useful tool. Feel free to start using it to maintain all of your code in other classes, and especially for group projects. You do not need an svn "server" so to speak, you can use subversion with direct filesystem access. Here is how you can create a repository in your home directory and use it for your other classes:

> svnadmin create ~/.repository
> svn checkout file:///home/$USER/.repository svn
> cd svn
> mkdir cs365
> svn add cs365
> svn commit -m "Adding directory for my CS365 class"

If you wanted to work on your stuff from home on your local computer, you could then check it out like this:

> svn checkout --username <user> svn+ssh://home/<user>/.repository/cs365

More Info

If you notice any errors in this tutorial or have any problems, please email mollenho at eecs.utk.edu