Quick Start to CVS

Brian Hargreaves
Other MRSRL CVS Links

I use CVS for just about any text files -- C-code, Matlab, HTML, LaTeX. Although I'm not a big expert in this, these steps will get you started. This tutorial is designed to be run on any UNIX/LINUX systems.

If you want the even quicker and dirtier start to CVS, click here.

1. Create a Repository

It is best to put your repository on a file system that is frequently backed up. Here I will just put it in my home directory, which is generally fine:

cvs -d ~/cvsroot init

Now you may want to add the following lines to your .cshrc, .bash_profile, etc file: (to find out what shell you are running, type echo $SHELL.)

.cshrc     .bash_profile
#CVS Environment variables
setenv CVSROOT $HOME/cvsroot
setenv CVSEDITOR emacs
    #CVS Environment variables
export CVSROOT=$HOME/cvsroot
export CVSEDITOR=emacs

That just tells the system where your default repository is, and for now you only need one repository. Now make sure that environment variable is set, by executing the line that you added, or equivalently:

source ~/.bash_profile

(or .cshrc if applicable).

2. Add a Project

Many ways to do this, none completely simple. Here's one that I tend to do. Let's say that you want to put your ~/tex directory under CVS (~/tex is a standard directory for documents preparation using LaTeX, but you don't really need to know anything about that here!). I have made a sample directory called ~/cvsexample that you can pretend is ~/tex for the sake of this tutorial. First, if you are running on our linux file system, copy the cvsexample and all directories to your home directory.

cd ~
cp -r ~brian/cvsexample .

Otherwise, if you are running on another linux/unix system, download the cvsexample.tar file. Move it to your home directory (~) and uncompress it using the following command:

tar -xvf cvsexample.tar

From here on, assume that this is important data that you don't want to lose -- next time you do this that will be the case!

Next, back up the whole project directory!

cd ~
mkdir cvsexample2
cp -r cvsexample/* cvsexample2/
(of course there are other ways to do this!)

Back it up again if you really care, because now you are going to erase your whole original cvsexample directory...

cd ~
rm -r cvsexample/*

Now we will add the (empty) cvsexample directory to CVS:

cd ~/cvsexample
cvs import -m "dir structure" cvsexample yourname start

"yourname" and "start" are really unimportant - they are just version and "vendor" labels. "cvsexample" tells CVS to store the archive in a directory cvsexample. Also, when you checkout cvsexample later, it will create a directory called cvsexample.

Note that any files/directories that are in cvsexample/ when you do the import command will be under CVS control. Sometimes that's desireable -- ie if you have three subdirectories of cvsexample that you want in CVS, just leave the empty directories. However, sometimes you don't want files under CVS, or you want to put them in as binary files. Thus I recommend adding them later.

Now you completely erase ~/cvsexample, because you're going to check it out as a CVS working directory:

cd ~
rm -r cvsexample

3. Check out a Project

This is the same for our example as it is for the case where another user checks out an existing project. Checking out a project in CVS will create a CVS working copy.

cd ~
cvs checkout cvsexample

Now you have a directory called cvsexample, which should have a subdirectory called CVS. (all directories under CVS control will have this subdirectory).

4. Adding Subdirectories

Adding subdirectories to CVS is desireable. I tend to add the empty directory to CVS, then put the files into it, which works fine.

cd ~/cvsexample
mkdir cartilage
cvs add cartilage

5. Adding files

First copy the .tex file from ~/cvsexample2 into cvsexample:

cd ~/cvsexample
cp ~/cvsexample2/*.tex .

Now, for any files that you want CVS to control, register them in the repository:

cvs add sample.tex

or something like

cvs add *.tex

You should get a message saying that CVS has added the files, but you should use CVS commit to permanently add them. Go ahead and commit them: cvs commit -m "original file" sample.tex


cvs commit -m "original files" *.tex

If you omit the -m "original file" then cvs will start up your default editor for you to type a log message. This latter form is usually more useful. Write good log messages!

6. Updating the Working Directory

Update is one of the most important CVS commands. It updates your working directory from the repository, but also tells you status of files. Try it:

cvs update

Probably all you got was a message like "cvs update: Updating ." Now "edit" ~/cvsexample.sample.tex by entering:

cp ~/cvsexample2/sample.1 ./sample.tex

Run cvs update again. The result of update will have the letter M next to the sample.tex, which you changed. This indicates that you have modified the file. Other letters you sometimes get are P, which means CVS has patched the file from other updates in the repository, or U, which means CVS has copied a new file that wasn't yet in the working directory.

Let's look at what we've changed with cvs diff:

cvs diff sample.tex

CVS prints a nice summary of what you've changed compared with the repository version. Now check in the change to the repository:

cvs commit sample.tex

When you do this, CVS pops up an editor. Just type a line like "first changes to file" on the first line and save/exit the editor.

Notice that the revision number is now 1.2.

7. Multiple Working Copies

You can have multiple working copies if you have more people working on the project, or if you have a copy on linux and also one on your laptop. We'll now check out a second working copy, and pretend we have a dummy user:

cd ~
mkdir dummyuser
cd dummyuser
cvs checkout cvsexample

This should create the cvsexample working directory within the directory dummyuser. Have a look at sample.tex, and note that the "edit" you made by replacing it with sample.1 is there. Now we'll assume that you and the dummy user both simultaneously make changes to sample.tex. First the dummy user:

cp ~/cvsexample2/sample.2 ./sample.tex
cvs commit -m "change by dummy user" sample.tex

Notice that the revision number is now 1.3. Then you make your independent change:

cd ~/cvsexample
cp ~/cvsexample2/sample.3 ./sample.tex
cvs commit sample.tex

Whoa! You and the dummy user made changes that are not compatible. Because CVS cannot resolve this conflict, gives you an error message that tells you that you need to figure it out. Now run cvs update again. It should give you a message that there are conflicts, and list "C sample.tex" to indicate this.

Edit sample.tex and you see that it shows you the lines that you need to resolve. Choose some balance between what you "wrote" and what the dummy user wrote, and just leave the file the way you want it to be. Then run cvs commit again.

Conflicts are a pain, but much less of a pain with CVS. You can avoid conflicts by using CVS update frequently. In that case, you might see the change that someone else has already made before you make a conflicting change. Of course sometimes conflicts will be unavoidable.

Next, you decide to add some files to the cartilage subdirectory:

cd ~/cvsexample/cartilage
cp ~/cvsexample2/cartilage/*.tex .
cvs add
cvs commit
cd ..
cp ~/cvsexample2/secondsample.c .
cvs add
cvs commit

Just type sensible comments when you do the commit.

Now become the dummy user again, and update the cartilage subdirectory:

cd ~/dummyuser/cvsexample/cartilage
cvs update

Notice that the .tex files are in the cartilage subdirectory. Change back one directory to cvs example and you see that secondsample.c is not there. That's because you ran the update from the subdirectory. To verify this, run cvs update from ~/dummyuser/cvsexample and you should see secondsample.c there now. The reverse if this is different though -- if you update the root, the subdirectories will all be updated. This is both useful and important to understand!

8. Log and Log Messages

Now go back to ~/cvsexample and have a look at the log messages for the file sample.tex:

cd ~/cvsexample
cvs log sample.tex

CVS prints a list of the log messages that you have added. A really nice feature is to have CVS just put the log messages in a comment block in the file each time changes are committed. Nicer yet is the fact the CVS does this intelligently enough that that comment blocks for latex, Matlab, html or C all work. Try it - put as the first line of sample.tex % XLogX, but replace the X with $. (Since this html file is controlled in my own CVS repository, I had to skew this a bit!

Now commit the changes and look at sample.tex. You should get your most recent comment (previous comments are not added). For fun, edit the new file, and remove the comment block and replace it with /* XLogX */ (again replace X with $) and commit the change again.

For another example, just look at the source of this web page with "view source" on your browser. Note that there are CVS log comments in this file!

9. Tags

Often, at certain points in time it is nice to mark all source files of a project. (Say at a point when code actually works...!) CVS is nicely set up to do this using the tag command:

cd ~/cvsexample
cvs tag Clinical-Release-1.0

The tag text can be anything that you like, so you can make good use of it. You could later checkout the tagged version of the project with cd ~
mkdir tempstuff
cd ~/tempstuff
cvs checkout -r Clinical-Release-1.0 cvsexample

10. Remote Repositories

If you are interested in having your repository on a different file system, you should first set (in .bash_profile or .cshrc etc) CVS_RSH to ssh.

Now you can check out a project from the different filesystem with the -d option, which tells CVS to use a different repository, and the :ext to tell it to use an external location. For example:

cvs -d :ext:bah@lelandmachine:/afs/ir.stanford.edu/users/b/a/bah/cvsroot checkout cvsexample

Now all your cvs commands will run through ssh to the remote system. You can avoid typing your password every time by putting the appropriate public key in your .ssh/known_hosts file. Since the remote repository location is stored in CVS/Root, you only have to type the :ext part once.

11. Where to Go From Here

This has been a fun little example. You can delete all the cvsexample stuff if you like now. Try putting something real into CVS, just to get yourself using it regularly.

CVS has fully compatible versions on Unix/Linux, Windows and MacOS. There are also simpler interfaces, web-based, or in Windows and Mac. When you're ready, here are some other links:

There are plenty of other tutorials on CVS too. Probably each person writes their own because they are all slightly biased to a particular need. A simple google.com search for "CVS Tutorial" will get you well on your way!
I would appreciate feedback on this. I'm not really an expert with CVS, so there may be much easier ways to do some of these things too.