Using Subversion

How to Use Subversion

Repositories: To use subversion, you first need a "repository," which is where the main copy of your data is stored, along with a record of all changes that have been made. For this class, we'll create a repository for each student (or group). For each project, your repository will be created via a request to our sys admin (send email to ianj@cs.brynmawr.edu - you need to specify your group membership and a name for the repo). You never make changes to the respository directly; rather, you'll make changes in working copy.

Once a repository is set up, the first thing you should do is "check out" a working copy of the repository. You'll do your work in the local copy, and then "commit" changes back to the main repository. To check out your repository:

svn checkout <repository location> <project folder location>

For example, I might checkout my CS355 repo (called cs355-dxu) using the command:

svn checkout https://svn.cs.brynmawr.edu/cs355-dxu cs355

This will create a folder at <project folder location> (cs355 for instance) in which you should do project development work. You can have multiple working copies; for instance, you might have one on powerpuff, and one on your home machine, allowing you to work easily in either location.

Adding new files: As you create project files, you should add them to the repository:

svn add <filename>

Only files that get added to the repository will be visible outside your local copy. However, files and new changes are not visible in the repository until you've "committed" them.

Committing changes: At regular intervals (i.e., once you get a new piece of functionality working), you should commit you changes to the repository. To commit, simply type

svn commit -m "A descriptive commit message"

This will commit all local changes in the current directory and all sub-directories. You can also commit a particular file:

svn commit main.c -m "A descriptive commit message"

When you commit you write a log message that describes the changes you're committing. If you don't want to specify this log message on the command line, you should set the SVN_EDITOR enviornment variable to your favorite text editor so that svn knows what to open for you to write ths message (you need to do this before you commit). My editor of choice is emacs; you might also use gedit or vim or nano. If you're using bash, add the following to your ${HOME}/.bashrc file:

export SVN_EDITOR=emacs

If you're using tcsh, add the following to your ${HOME}/.cshrc file:

setenv SVN_EDITOR emacs

Updating your local copy: If you have multiple copies of the repository in different locations, or if you're working in a group, you'll want to update your local copy to reflect recent commits:

svn update

This will pull in all recent changes for this directory and any sub-directories. In general, svn update should be the first command you run before starting to code for the day.

Status: You may want to check the "status" of your local copy:

svn status

This will tell you which files have been added or modified, and will also tell you which files are not currently under version control. You can use this to check if you've forgotten to add any files to the repository. svn help status will tell you more about all possible status.

Reading the log: You'll likely want to read the commit log to see what changes have recently been made, or to find a previous version you want to which you want to revert:

svn log

This will only print the log messages. If you want to see what files were modified, you should use:

svn log -v

Learning more: To find out more about a particular svn command, use

svn help <command>

I'd also highly recommend the e-book listed above (svnbook.red-bean.com) if you want to learn more.

How to Use Subversion in a Group

For most projects in this class, you'll be working in groups. While you may find yourselves most productive when working together on a single workstation, it's likely that you'll work on some portions of the project individually and then want to combine your efforts. This is one excellent reason to use version control, and subversion makes it faily simple to work on your own and then combine code.

When you sit down to work on your code, you'll likely want to svn update to pull in any recent changes that your partner has made. When you're done making changes, you should svn commit so these changes will be visible to your partner. In a perfect world, this series of events would look something like:

Alice: svn update
Alice: [works for a while]
Alice: svn commit
Bob: svn update
Bob: [works for a while]
Bob: svn commit
...

However, it's certainly possible (likely, even) that you and your partner will individually work on the same file or section of code simultaneously. This might look like:

Alice: svn update
Alice: [works for a while]
Bob: svn update
Bob: [works for a while]
Alice: svn commit
Bob: svn commit
> svn: Commit failed
> svn: File 'hello.c' is out of date

Here, Bob needs up date to the most recent version (with Alice's latest commit) before he can commit his changes. Sometimes, this update goes smoothly and then Bob is able to commit. However, it's possible that when Bob runs svn update, he'll get with a "merge conflict," meaning that subversion doesn't know how to reconcile his local changes with the latest version. Here's how that could happen (example written by Evan Driscoll):

Suppose both Alice and Bob start with the same file:

#/usr/bin/env python
print "Hello world!"

Now Alice decides that the message should have a comma in it:

#/usr/bin/env python
print "Hello, world!"

Meanwhile, Bob decides that the message is a little too overstated and wants to tone it down a little bit:

#/usr/bin/env python
print "Hello world."

Now Alice commits, so the current version in the repository agrees with her. Bob tires to commit and gets a message about not having the current version. So he updates and subversion informs him that there is a conflict. Subversion will ask what to do; sometimes you can resolve this right away, but assume Bob answers p to postpone (this process varies from version to version).

Bob's working copy of the file has been edited with the conflict markers:

#/usr/bin/env python
<<<<<<< .mine
print "Hello world."
=======
print "Hello, world!"
>>>>>>> .r4

The <<<<<<< and >>>>>>> denote a conflict, and ======= separates the versions. The top version is Bob's local copy, and the bottom version is the version that Bob pulled from Alice (.r4 is the current revision in the repository).

Bob then looks at what Alice changed and decides how he wants to integrate the changes. Perhaps like this:

#/usr/bin/env python
print "Hello, world."

He manually makes this change in an editor, saves the file, and then commits.

In a small group, it is usually easier to just agree to work on separate aspects of the project, which are divided into distinct files so that commit conflicts do not happen in the first place.