Introduction to CVS

This is a short introduction to CVS, intended for clients who will not be setting up a repository, but only using one which has already been set up for them. First, some basic concepts.

CVS stands for Concurrent Versions Systems, and is a version control system. The primary purposes of a version control system are:

All information stored by CVS, including current documents and the full history of all their changes (so that all past versions are available) is stored in a repository. The repository usually has a single physical location, accessed by many users over a network. To access your CVS repository, you'll first need to set up your CVS client.

Setting up your CVS client

The first thing you need to access CVS is a client. Under most UNIX systems, the client "cvs" will already be available. Under Windows, a good client is Tortoise CVS. A third alternative is to directly access the local repository from a shell account on the machine the repository is installed on. In the first two cases, I will be assuming that you be operating CVS over SSH, which is the most common way now.

Setting up cvs

Under UNIX, cvs is a popular command-line client for CVS. To set it up usually requires that you set two environment variables. Under bash, you do this thus:

export CVS_RSH=ssh
export CVSROOT=<your CVSROOT, supplied by your CVS administrator>
(Angle brackets should not actually be typed). You should then be able to checkout a project with a given name by using:
cvs checkout <project name>
You will be asked for a password each time you perform a CVS operation. This is your SSH password.

Setting up Tortoise CVS

Go to Tortoise CVS's web site and download and install the latest stable release. This will require a reboot, because Tortoise CVS is a shell extension; that is, it works entirely through additions to the behaviour of Windows Explorer.

Next, within My Computer locate the place where you wish to checkout the CVS project, right-click, and choose "CVS Checkout...". This will bring up an initially empty dialogue that looks something like this:

Tortoise CVS Checkout Module dialogue

You can simply fill in the CVSROOT supplied by your administrator in the box at the top, and fill in the project name in the Module box at the bottom, then hit OK. The other fields will be filled in automatically.

The checkout will ask you for your password. This is your SSH password. Afterwards, you can enter the newly created directory and right-click on files to perform CVS operations on them. Overlays on the icons will indicate each file's current status.

For a very good explanation of using TortoiseCVS for all your daily CVS needs, see the TortoiseCVS Daily Use Guide that comes with TortoiseCVS, under your Programs menu. The rest of this document will focus on the command-line cvs.

Using cvs locally

You may wish to use cvs locally on the machine on which the repository lives. This is convenient because repository access is very fast and requires no authentication. The disadvantage is that it may be more difficult to do development directly on the remote machine.

To use cvs locally, SSH to the machine on which the repository is installed, and then use this command:

export CVSROOT=<CVSROOT>
where CVSROOT is the portion of the CVSROOT supplied by your administrator following the last colon (:). For example, if you were given "CVSROOT=:ext:moonflare.com:/projects/stuff", the CVSROOT you would enter above is simple "/projects/stuff".

You can then proceed to use

cvs checkout <project name>
to checkout your project into the home directory of your shell account. No password will be asked for.

Basic CVS Operations

Note that the rest of this document applies only to the command-line cvs.

Once your project is checked out, change into the directory that was just checked out. You'll notice every directory in this directory tree will contain a subdirectory called CVS. This contains important information CVS uses, but is not where the actual repository data is stored.

The most important things you'll do with CVS are adding and removing files, modifying files, and retrieving others' modifications. These are detailed below.

Adding Files

To add a file, create the file first and then simply use:

cvs add <file name>

Your file is not yet added to the repository, however! To do this you must also commit the file:

cvs commit -m "Message describing purpose of file" <file name>

You may also do a batch commit, and this will commit this new file along with all your other changes to the repository:

cvs commit -m "Message describing all changes"

I emphasize that generated files, that is, files that are automatically produced by tools from other files in the repository, should never be added to the repository. Other users can always produce their own up-to-date version from other files in the repository, and adding these files only causes confusion.

Removing Files

To remove a file from the repository, delete the file first and then simply use:

cvs remove <file name>

Your file is not yet removed from the repository. To do this you must also commit the (no longer existing) file:

cvs commit -m "Message describing why file was removed" <file name>

You may also do a batch commit, and this will commit this removal along with all your other changes to the repository:

cvs commit -m "Message describing all changes"

Note that all previous versions are kept in the repository, even after the removal; it will simply not appear in current checkouts.

Modifying Files

When you do a checkout or update, files will be placed in your CVS tree. You can edit these, and then, when you feel confident your changes are correct, you can commit them to the repository using the commit command:

cvs commit -m "Message describing what was changed" <file name>

This may fail if another developer has been working on the file at the same time. In this case you must do an update first; see the next section.

If you can't remember what you changed, try this command:

cvs diff <file name>

For textual files, this will list all changes you have made but not committed.

Retrieving Others' Modifications

To retrieve any modifications made by others, issue this command in the root directory of your CVS tree:

cvs update -d

The -d tells CVS to retrieve any new directories that have been added as well.

The above command may result in conflicts, if you have been working on a file at the same time as another user. You will know because in the list of files that appears, files with conflicts will appear with a "C" next to them. See Checking Your Status and Handling Conflicts for details.

Handling Conflicts

One powerful feature of CVS is that it allows multiple developers to edit the same base document at the same time, and both check in their changes. CVS often is powerful enough to merge these changes successfully, so that no special action is required to resolve this apparent paradox.

Occasionally, however, during an update conflicts will occur. This means CVS could not merge the changes successfully, and requires something more intelligent (you) to merge the changes by hand. It will indicate which files had conflicts with a "C", and you can then edit these files and search for the markers indicating a conflict, which look something like this:

<<<<<<< filename
    your changes
=======
    the same portion from the repository
>>>>>>>

You must choose which portions you want from your own changes and from the section from the repository, and erase the marking line CVS created. Then after verifying the new document is correct, you can commit your changes.

Viewing Change History

There are two types of change history you can view. During every commit every user should give a short message explaining what they changed. To view these, type:

cvs log <file name>
You may wish to pipe this to less, as it often generates a lot of output:
cvs log <file name> | less

Another way you can determine what was changed is to ask CVS exactly what was changed. You do this with the diff command. This command has great flexibility. Here are some simple examples:

cvs diff <file name>

This views all changes you've made to a file since you last committed it.

cvs diff -r1.2 -r1.3 <file name>

This views all changes made to a file between revisions 1.2 and 1.3.

cvs diff -D "1 day ago" <file name>

This views all changes made to a file in the last day.

Finally, by leaving out the filename, CVS will perform the corresponding diff on all files in the current subdirectory tree.

Checking Your Status

You may often want to check which files need to be updated, which files you've modified, and so on. The easiest way to do this is with this command:

cvs status | grep File

To just view files that you've modified, try this command:

cvs status | grep "Status: Locally Modified"

When you perform an update, a list of files will appear. A character appears to the left of each filename, and these indicate respectively:

? This file is present in your working directory but not in the repository. You may want to add it.
U A file you had not modified was updated based on someone else's changes.
P Same as U.
A This file has been added but not yet committed.
R This file has been removed but the removal not yet committed.
M This file has been locally modified by you, and either no one else has changed it yet, or any changes they made were successfully merged with yours (but your changes will still not enter the repository until you do a commit).
C This file was modified by both you and someone else who already committed their changes, and these changes could not be merged successfully. See Handling Conflicts.

To Learn More

There's a lot more you can do with CVS beyond these basic operations. To learn more, read the official CVS documentation available at CVS Home, in particular the famous "Cederqvist".

Back to Documents

Back to main page