Basic CVS usage

First of all, before doing anything else, you have to tell CVS what repository to use. It gets that information normally from the CVSROOT environment variable. For our environment, you want to set CVSROOT to /afs/ir/dev/cvs. The easiest way to do that is probably to put:

    setenv CVSROOT /afs/ir/dev/cvs

in your .cshrc.

There's only one CVS program to run, and all commands are given as the first word on the CVS command line. For example, if you've changed a file in CVS and want to commit your changes to the repository, type:

    cvs commit <filename>

where <filename> is the name of the file you changed. This is one of the most common things to do. You can give cvs commit more than one file at a time, and all those files will be committed with the same log message provided they're all in the same directory. Note that nearly all CVS commands are recursive if given a directory instead of a file as an argument, so if you instead type:

    cvs commit .

CVS will recursively commit all changes in your current directory and any subdirectories (opening an editor window for you to enter a log message for each directory's worth of files).

Obviously, you can only make changes and commit them if you already have a checked out copy of that portion of the repository. If you need to create such a checked out copy (to have your own set of files to work with, for example, or to work on something that doesn't have a canonical checked out copy in AFS somewhere), type:

    cvs checkout <module>

<module> either a path within the repository or a CVS module name, usually a module name. CVS modules are just symbolic names for sets of files, generally just symbolic names for a particular directory in the repository. For example, the module "news-template" refers to the path leland/news/template in the repository.

The full list of modules in our main CVS tree are in the file:


cvs checkout will create a subdirectory for the checked out copy, usually named after the module but sometimes named something else (the name of the checked out copy can be set in the modules file mentioned above). If you want to use a specific directory name, overriding the default, you can do that with:

    cvs checkout -d <directory> <module>

Also note that "checkout" can be abbreviated as "co".

Note that you generally only have to worry about module names (and the repository location) when you're doing a checkout; when CVS creates a checked out copy of a part of the repository, it sprinkles CVS directories throughout it, and in files in those directories puts the path to the repository and the path within the repository that this checked out copy refers to. Subsequent CVS commands within that directory structure use that stored information and don't require that you specify it every time.

To get rid of a checked out copy once you're done with it, cd to a directory above where you checked it out and type:

    cvs release -d <directory>

where <directory> is the name of the directory holding the checked out copy. This command will check to make sure you don't have any uncommitted local modifications and then will delete the checked out copy for you.

If you add a file or delete a file, you need to use special commands to tell CVS about that change. To add a new file to the repository, first create the file in your checked out copy and then type:

    cvs add -m'Brief description.' <filename>

The -m flag adds a brief description of what the file is to the repository (this should probably not be longer than a single line). It's considered good form to use the -m flag, but you can leave it off and CVS won't complain. After doing a cvs add, you still have to do a cvs commit of the file to store the first revision in the repository.

If the file you're adding is a binary file, add the flag -kb to the cvs add command. For example, here's the complete set of commands for adding a new .gif file to the repository:

    cvs add -m'Some generic image.' -kb image.gif
    cvs commit image.gif

Deleting a file involves similar steps. First delete the file out of your checked out copy, then use cvs remove to mark it as deleted, and then use cvs commit to commit the change:

    rm <filename>
    cvs remove <filename>
    cvs commit <filename>

You can combine the first two steps by using:

    cvs remove -f <filename>

if you wish.

To add a new subdirectory to the repository, first mkdir the directory and then cvs add it. This is a special exception to the otherwise general rule that all changes have to go through cvs commit before they take effect; when you cvs add a directory, the corresponding directory is created in the repository and a notification message is sent out right away.

If there is more than one checked out copy, and someone has committed changes from a different checked out copy than the one that you're using, those changes won't automatically show up in your copy. Instead, to update your copy from the repository and pick up any changes that have been made elsewhere, type:

    cvs update

(You can give update a filename or a directory as an argument and have it only affect that filename or directory; by default, it recursively updates everything in or under the current directory.)

cvs update prints out a notification message every time it finds something different between your copy and the repository, with the first letter indicating what it did. "?" means that CVS doesn't know about that file (maybe it's new and you haven't run cvs add on it yet). "U" means that a file was updated from the repository. "M" means that the file has local uncommitted modifications and the file was left alone.

"M" usually means that you've made modifications to the file but no one else has. There's also a possibility that both you and someone else have made modifications to the same file. This sounds like a potential disaster, but in fact CVS is well-equipped to deal with this, and even encourages this way of working. If you and someone else have both made changes and the other person has committed their changes since the last time you updated your tree, CVS will do a three-way merge between their revision in the repository, your local copy, and the revision that both of you started from. It will attempt to merge their revisions into your copy so that you don't have to do anything. This works well if you weren't both working on the same part of the file.

If you were working on the same part of the file, you may see a "C", which indicates that CVS tried to merge and found conflicts. CVS will save an unmodified copy of your local file with a name starting with ".#" and will modify your local copy to contain both versions. You will then need to go and edit the file by hand and decide how to resolve the conflict. The beginning of the conflicting region will be marked with a series of >s, the division between the two alternatives will be marked with a line of =s, and the end of the region marked with <s. You'll need to delete those lines and decide what that section of the file should look like, save the result, and then use cvs commit to commit the merged copy.

Conflicts are in practice extremely rare and usually mean that people aren't coordinating what they're doing very well.

If you want to get a report on what's changed between your copy and the repository, but don't want CVS do actually do anything, use the command:

    cvs -n update

To see the differences (in diff format) between a file you've modified and the last committed revision in the repository, use:

    cvs diff <filename>

(You can also give cvs diff multiple filenames or even whole directories and it will produce a series of diffs.) cvs diff takes the standard flags to specify what type of diff to produce, so:

    cvs diff -u <filename>

will produce a unified context diff (the type that most people prefer).

Finally, if you find yourself using certain options all of the time, you can associate default options with CVS commands by putting them in a file named .cvsrc in your home directory. For example, to make cvs diff always produce unified context diffs, put the line:

    diff -u

in ~/.cvsrc.

For details on the many other CVS commands, as well as a more detailed description of the syntax (and a good explanation of why some options come before the command and some options come after the command), see the CVS manual, which you can access by typing:

    info cvs

For details on more advanced problems, such as renaming files, renaming directories, changing revision numbers, and other operations, see the rest of the local CVS documentation.

As a final warning, the CVS documentation recommends using the "import" command to put a large group of files into CVS for the first time. Don't use this. It creates branches and tags that are inconsistent with the way our repository is set up (basically, it works but it adds a bunch of needless complication to the repository files and will make revision numbers look odd). Instead, see the separate documentation on creating a new CVS module.

Last modified and spun 2014-08-17