Subversion

Subversion (svn) is a tool to track different versions of text files. If you are using Windows, you should get TortoiseSVN, which enables shell integration of svn. Only the commandline version is covered. Most of these commands are in the context menu for TortoiseSVN. I am using some bash notation, but it should be similar for other shells.

Making a repository

Before using svn, you must tell it where to keep all of this information. The first step is to decide on what structure you want to use to store the files. This structure is analoguous to the directory hierarchy used in most filesystems. Also, you must decide if the repository is only going to hold 1 project or many. Most guides recommend naming the main part of the repository trunk.

The naming scheme that I use has the name of the projects at the highest level, with active and release below that. Active has current for the current main branch. If I was going to work on maintaining older versions, I would have those older versions in active as well. Releases has the versions that I have released or want to be able to refer to by name. I do not modify those.

An example of my layout:
DirectoryComment
project_aEverything about Project A
activeVersions that are still being worked on
currentThe current version
v1An old but still maintained version
releaseVersions that will no longer be modified
v1.0Project A v1.0
v2.0Project A v2.0

Once you have decided on a layout, organize the files of your initial version into that structure. Be sure to remove all of your temporary and intermediate files, otherwise they will get added also. For convenience, you can put the SVN path as an environment variable.

Adding the environment variable for the path to the SVN repository:
export SVNROOT='file:///home/user/svn'
Creating an empty repository:
svnadmin create "${SVNROOT#file://}"
Adding the initial version from path:
svn import path/ "${SVNROOT}"

It will prompt you for your comments. Save your comments and exit the editor. It should say that it has "Committed revision 1.". Now you should check out the new version and work with it from now on. You should try this from another directory first to be safe.

Checking out the version from svn to outpath:
svn co "${SVNROOT}/repos_path" outpath

Checking out and committing

Now that you have a repository, you must be able to interact with it. Copying a version from the repository is called checking out. Adding your changes to the repository as a new version is called committing. I will assume that you have already set the environment variable SVNROOT.

Before you start working with a repository, you must check out a version of it.

Checking out from svn:
svn co "${SVNROOT}/repos_path" outpath

This will go into the repository, then into repos_path and save the current version there as outpath. In addition to your files, you will notice that each directory also has a .svn directory in it. This directory contains bookkeeping information for svn in it. It also contains the checked out versions of the files in it.

Now you should edit the files as you normally would, with 1 exception. Filesystem operations must be done through svn instead of directly so it can follow what is going on.

Copying a file:
svn cp src dest
Removing a file:
svn rm src

svn will carry out the action and mark these actions to be committed to the repository. Once the files are in the new shape that you want them, you can commit your changes back to the repository.

Committing:
svn commit

After putting in your comments, all of your changes will be saved. To be safe, you should update so you know that all of your files are up-to-date. If you don't it might get confused if you try to view the log or if other people have also made commits.

Updating:
svn up

The point of this was that if anything went wrong, you could revert to an earlier version.

Check out version 1:
svn co -r 1 "${SVNROOT}/repos_path" outpath
Check out the version from the beginning of 2006:
svn co -r {2006-01-01} "${SVNROOT}/repos_path" outpath

Copy, in addition to working on files, also works on entire directories. Furthermore, neglible additional space is needed for that copy. This can be used to tag releases so you can easily check out that release the same as you would check out any other directory.

Copy a directory as a release:
svn cp "${SVNROOT}/proj/active/current" "${SVNROOT}/proj/release/v1"

So far, I have used "file://" as the protocol. This is for files that are available through the local filesystem. Other protocols are available as well. A particularly useful protocol is svn+ssh. It allows you to connect to another machine and access the repository through ssh using svnserve.

Accessing host as svnuser with svn+ssh:
svn co svn+ssh://svnuser@host/path_to_repos/path_in_repos

Unfortunately, due to a bug, if you are using password authentication, it will ask you for your password 3 times even though you are typing it in correctly.

Accessing host over plain HTTP:
svn co http://host/path_to_repos/path_in_repos

Subversion also supports plain HTTP and commiting with webdav. This is very useful for easy, anonymous checkouts, for if you want to make your repository publicly accessible. It also supports having passwords for commiting and fine-grained access controls if you so desire them.