he designers of Subversion have created an open-source version control tool that fixes the flaws and addresses shortcomings in the popular Concurrent Versions System (CVS) version control system. The following are the most significant and visible CVS flaws that Subversion rectifies:
- CVS lacks directory versioning. It keeps track of only files, not directories.
- CVS has weak support for the copy, rename, and delete operations on files, a result of the lack of directory versioning.
- CVS lacks atomic commits.
In addition to these highly visible shortcomings, CVS also has the following less obvious shortcomings:
- CVS lacks versioned metadata. It can remember file permissions, but that is about it.
- CVS is hard to extend. There is no API that makes extension an easy process.
Subversion provides the following features that either fix the CVS flaws or improve upon existing CVS features:
- Subversion tracks both files and directories. So when you delete directories, they stay deleted in checkouts?no more specifying the “-dP” option to prune empty directories.
- Subversion handles the copy, rename, and delete operations on files well.
- Subversion performs its commit operations in an atomic fashion. So you will never have an inconsistent code tree as a result of the version control tool. Subversion ensures that either the entire commit or none of it happens. You will never get the situation in which the commit breaks in the middle, leaving some files checked in and others not. Subversion rolls back the whole commit operation, similar to how a relational database operates.
- Subversion provides a well-documented API that allows other applications to embed or extend it.
- Subversion has a uniform method of dealing with all files, both binary and text. It has a binary differencing algorithm that works on text files. You no longer need to tag files as binary or text.
- Subversion has more ways of accessing the repository. While CVS has direct filesystem, pserver, and ssh/rsh remote access, Subversion has direct filesystem, svnserve (analogous to pserver), ssh, and WebDAV. The Subversion API is extensible and makes it easy to add more types of access (for instance, integration with your favorite IDE).
- The powerful API means that Subversion can be extended in ways that CVS cannot (for instance, with new access methods or with new storage backends).
This article first describes how easy it is to start with Subversion by creating a new repository. CVS users should find it especially easy. Next, it shows how to connect to a Subversion repository and how to operate on the newly created repository with commands to modify its contents (operating on files and directories within the repository). It then describes how you will typically use Subversion commands in day-to-day development, showing some of the frequently used commands. Finally, it addresses two advanced Subversion topics: wedging, an infrequent and harmless problem, and branching/tagging, ways of organizing versions of file sets.
CVS to Subversion: An Easy Switch
In order to make the tool easy to use, the Subversion designers adopted many of CVS’s commands and usage patterns. This means that not only do you get to use the same commands, but you also use them in the same way for the most part. Switching to Subversion from CVS is therefore very easy. It is also easy to pick up Subversion from scratch.
To demonstrate how Subversion works, the following instructions show you how to start using it on a sample project. You need to have Subversion already installed on your computer. (To download Subversion, go to subversion.tigris.org and find the latest version.)
The first thing you must do is set up a repository. The repository, a simple directory with some subdirectories and files, holds all of the files pertaining to your project. You can have multiple repositories on a single machine or filesystem, and you can store the repository anywhere on your filesystem (although it should be a local filesystem, not an NFS or otherwise remote filesystem?an upcoming section discusses how to set up a repository on local filesystems or other machines).
For the most part, you will deal with two commands when using Subversion: svnadmin and svn. You will use the svn command almost all of the time. The commands check out, commit, update, difference, and other operations are all present in the svn main command. You will use svnadmin to create and maintain your repositories.
To create the repository on your local filesystem, issue the following command (do not actually issue this command right now):
svnadmin create /path/to/repository
You do not have to be root to create a repository. However, if you want other people to be able to check out items and/or commit items to your repository, they must have permission to do so. The best way to do this on a Unix system is to put the users in a group and then make the directories and files in the repository readable by that group. You should make the directories and files in the repository writable by the group if you also want to allow group members to commit to your repository.
To create the repository, first make sure that you have a directory called “/srv/svn”. If you do not have this directory on your filesystem, create it. Make sure it is writable by the user who will be creating the Subversion repository. If you do not have root access, you can use another directory, but make sure to substitute that directory whenever the instructions specify /srv/svn. Issue the following command:
svnadmin create /srv/svn/first-project-repository
If you view the contents of the /srv/svn directory, you will see a first-project-repository subdirectory. If you look inside the first-project-repository directory, you will see a directory listing like the following:
drwxrwxr-x 2 wchao wchao 4096 Dec 27 15:25 confdrwxrwxr-x 2 wchao wchao 4096 Dec 27 15:25 davdrwxrwxr-x 2 wchao wchao 4096 Dec 27 15:25 db-r?r?r? 1 wchao wchao 2 Dec 27 15:25 formatdrwxrwxr-x 2 wchao wchao 4096 Dec 27 15:25 hooksdrwxrwxr-x 2 wchao wchao 4096 Dec 27 15:25 locks-rw-rw-r? 1 wchao wchao 376 Dec 27 15:25 README.txt
The contents of the first-project-repository, as you can see, are just regular files and directories. You should not, however, touch these files. The svn command operates on the files in the repository, so you should not need to touch them directly unless the repository gets wedged (more on that in the “Wedging, Branching, and Tagging” section at the end).
Time to Operate on Your Repository
Now that the repository has been set up, you can operate on it. You will usually be in one of two situations after creating a Subversion repository:
- You have some code you want to put in the repository immediately.
- You are just beginning a project and have no code yet.
If you’re in the first scenario, you can either import your code into the Subversion repository using the import command, or you can copy the existing code into your working copy (discussed in the next paragraph) and then add it to the repository with the “svn add” command (discussed in the upcoming “Subversion in the Development Process” section). This tutorial does not cover the import command, but you can find out more about it in the Subversion manual.
For now, assume you are starting from scratch. Now that you have created the repository, you need to check it out and create a working copy in which you can create and change files. The working copy is where you work on your files in isolation from other developers. Use the following command to check out your working copy:
svn checkout file:///srv/svn/first-project-repository first-project
This command checks out the first-project-repository and places it in a directory called first-project in the current directory. If you did not want the first-project directory in the current directory, you can simply move it to another location.
Note that there are three slashes after “file:”. The first two slashes are part of the URL protocol identifier. The analogous situation with Web access is how Web site URLs always have “http://” in front of them (note the two slashes after the http). The third slash after “file://” is part of the path?in other words, the path is “/srv/svn/first-project-repository”. Subversion supports several protocols in the standard distribution (see Table 1).
|file||Direct access (local filesystem repository)|
|http||Transport via WebDAV protocol on Apache server|
|http||Transport via WebDAV using SSL to encrypt data|
|svn||Transport via custom protocol with svnserve server|
|svn+ssh||Transport via custom protocol with svnserve server, tunneled through ssh connection|
|Table 1. Protocols Supported in Standard Subversion Distribution|
To access a Subversion repository on another machine, you must use one of the network protocols (http, https, svn, or svn+ssh). The easiest protocol to set up probably is svn+ssh, if you already have ssh access to the remote machine. In that case, you do not have to do anything further to set up remote access to the repository (apart from creating the repository with the svnadmin create command on the remote machine, of course).
Now that you have checked out a working copy of first-project, change into the first-project directory that you created by issuing the “svn checkout file:///srv/svn/first-project-repository first-project” command before. Issue the following commands:
svn mkdir branchessvn mkdir tagssvn mkdir trunksvn commit
The last command (the commit operation) will ask you to enter a log message. Just enter “started project”, and then exit the editor. Subversion should check in your changes.
You might be wondering why you just created three directories. The accepted way of handling branches and tags in Subversion is through file and directory operations. CVS has a tag command (more accurately, the “cvs tag” command) that provides branch and tag functionality. In Subversion, the branch and tag functionality are implicit because you can create copies of files and directories and tell Subversion to remember that the copies are related to one another. In other words, you can create branches and tags by simply telling Subversion to copy the trunk directory to a new directory underneath either the branches directory or the tags directory. An upcoming section elaborates on branches and tags.
Subversion in the Development Process
For now, move on to creating some actual project files and seeing how to work with Subversion in the development process. First, clean up:
cd ..rm –fr first-project
Once you have committed your changes, you can delete the working copy. If you plan to make further changes, you can leave the working copy and just make your changes in it. Normally, you would leave your working copy, but you will check out a different directory before creating some code files that you will add to the project. Issue the following commands:
svn co file:///srv/svn/first-project-repository/trunk first-projectcd first-projecttouch Car.javasvn add Car.javatouch Dealer.javasvn add Dealer.javatouch Customer.javasvn add Customer.javasvn updatesvn commit
Note the difference: you just checked out the trunk, but told Subversion to put it in a directory called “first-project”. The trunk is where active development should occur most of the time. The “co” is shorthand for “checkout”. For a list of shorthand, type “svn help”. You created three code files. The touch command simply updates the timestamp on a file, creating the file if it does not exist. This tutorial used it simply as a quick way to create the three Java source files, which are zero byte files. Obviously in your development sessions, you will create code in the Java source files rather than leaving them as zero byte files. The “svn add” command tells Subversion that you want to add a file (or multiple files specified by a wildcard) to the repository for version control.
The reason you issued the “svn update” command is that it is important to resolve conflicts before checking in your changes. In fact, Subversion will not allow you to commit your changes if you are not up to date. The commit operation will abort and roll back. Subversion will tell you that your working copy is out of date. When you perform the update, Subversion may update some of your files with no conflicts. Other files may have conflicts (e.g., you tried to change a section of code that another person also tried to change). In cases of conflict, you must resolve the conflict before committing. You will most likely find yourself in the following cycle when using Subversion:
svn co file:///srv/svn/first-project-repository/trunk first-projectcd first-projectwrite code or make changes to existing codesvn updateresolve conflicts (if any)svn commitwrite code or make changes to existing codesvn updateresolve conflicts (if any)svn commitwrite code or make changes to existing codesvn updateresolve conflicts (if any)svn commitetc., etc. , ...
The “svn update” commands keep you in sync with other developers, who work on their files in their own working copies of the repository. If you go for long periods before committing changes, it is still good to issue “svn update” commands every once in a while in order to ensure that you don’t stray too far from the evolving code base. If you don’t commit that frequently, your development process would look like this:
write code or make changes to existing codesvn updateresolve conflicts (if any)write code or make changes to existing codesvn updateresolve conflicts (if any)write code or make changes to existing codesvn updateresolve conflicts (if any)svn commit
Table 2 lists the other svn commands that are frequently used during a development session.
|delete||del, remove, rm||Delete a file from the current revision of the repository.|
|move||mv, rename, ren||Move a file in the repository to a new name. Rename is the same as move, if you think about it.|
|diff||di||Show the differences between one revision of a file and another revision of the file.|
|revert||N/A||Revert the specified file or files to the revisions at checkout time.|
|copy||cp||Copy one or more files or directories. When both arguments are URLs, the copy command performs branch and tag operations.|
|Table 2. Frequently Used svn Commands|
The “svn help” command also is useful. You can obtain general help with “svn help” or quick help on any svn command with “svn help command“.
Wedging, Branching, and Tagging
Because it relies on the Berkeley DB filesystem as its standard repository storage backend, the repository occasionally will become “wedged”. The Berkeley DB filesystem occasionally becomes wedged when it tries to perform a transaction but cannot because of a race condition occurring from simultaneous access. The Berkeley DB provides many important features?most notably database transaction semantics?but occasional wedging is one of its weaknesses. When that happens, further transactions are prevented and you cannot access the Subversion repository. Fortunately, wedging occurs infrequently and is also harmless as long as it is treated right after it happens. When it does, issue the following command to fix the problem:
svnadmin recover /path/to/repository
It is important to run the “svnadmin recover” command as the user who manages the repository (who may or may not be root). If you run it as a different user, you will need to change the permissions on the repository files afterwards to allow the Subversion users to access the repository. In order to prevent corruption of a wedged repository, Subversion will not allow you to use a repository that has become wedged.
The previously mentioned branching and tagging are easy to use in Subversion. In contrast to CVS, there are no special commands for dealing with branches or tags. Subversion treats them simply as other directories in the virtual filesystem that it creates in the repository. Taking the example of first-project with Car.java, Dealer.java, and Customer.java, you can issue the following command to create a branch:
svn copy file:///srv/svn/first-project-repository/trunk
Now Ted can work on his branch and check in changes to his branch without affecting others working on the trunk. When he is ready to merge his changes back with the trunk, he issues the following command:
svn merge -r 101:HEAD file:///srv/svn/first-project-repository/trunk
Replace 101 with the revision as determined by the following command:
svn log ?verbose ?stop-on-copy
Tags are the same as branches. You create a tag with a command similar to the following:
svn copy file:///srv/svn/first-project-repository/trunk
The difference between a branch and a tag is purely user-defined. Subversion does not treat tags differently from branches. You may think of a tag as a snapshot of the code base at a given point in time. The only way in which tags are different from branches is that you (and other users) refrain from committing any changes to them. With the release-2.2 tag shown previously, you could always get access to the version of the code base used to build release 2.2 by simply checking it out as follows:
svn co file:///srv/svn/first-project-repository/tags/release-2.2 rel-2.2
Subversion Is Just Better
As this tutorial has demonstrated, Subversion is a highly useful tool that is superior to CVS. Whether you are beginning a new project or you have an old project that uses CVS, you should strongly consider using or switching to Subversion.