CVS "quick reminders"

This is not intended to be an exhaustive discussion of CVS. For that, you should go to
A repository is the master collection [of projects].
A project is a collection of related files.
A module can be a part of a project. A directory in a project, for example.
A sandbox is a project being edited.

CVS ready-reference, optional items are [bracketed and in blue]
Description command
sanity check : *IF* you updated now, what would happen? Very useful. The -dRP option is useful and painless. I always put it in. [update details] cvs -nq update [-dRP]
Update your sandbox: incorporate all the changes in the most recent repository version into the files in your sandbox. The changes you may be making are maintained, as long as there are no conflicts. Conflicts are marked with some characters intended to attract your attention. The -d option ensures that all new directories are added, R indicates to process recursively, and P results in the Pruning of empty directories (which is more common than you think) ... cvs update [-dRP]
Commit the changes to the repository. cvs commit [-m "message goes here"] [file1 file2 ...]
Check the log of a file: cvs log file
Tag: This groups the files together into one logical "version". This is akin to bundling a collection of files into "Version 1.2" (some old, some new, the whole thing is now 1.2). In this example, "xxx" is a unique tag YOU must define. HEAD is a special tag, always relating to the most recent one. cvs tag xxx
Status: report the status of the project, "-v" includes tags, which is useful when trying to figure out what the next tag should be. cvs status [ -v | less ]
Export: The "export" process is nearly identical to the "checkout" process, but the CVS administration files are omitted. This is particularly useful when bundling software for distribution. In this example, "xxx" is the project. cvs export -r tag xxx
Differences: Check the difference of current version of a file with the previous sandbox version cvs diff [file] [ | less ]
Differences: Check the difference of current version of a file with the latest repository version (HEAD is a special tag) cvs diff -r HEAD [file] [ | less ]
Differences: between one "tag"ged version and another "tag"ged version cvs diff -r tag1 -r tag2 [file] [ | less ]
Add to repository: add a file to the repository. This actually only updates the list of files to be maintained. To actually commit to the repository, you must cvs commit, naturally. cvs add is usually followed by cvs -nq update to make sure all the files you want to add are added, and gives you the chance to remove some files from the repository, etc. cvs add file1 [file2] [...]
Remove from update list/repository. Occasionally there are files in your sandbox or repository you do NOT want to update. Usually, you find them with cvs -nq update Again, nothing actually happens until you cvs update cvs rm file1 [file2] [...]
Creating a new sandbox. This presumes your CVSROOT variable is set properly, and there is a project named xxx with the right permissions. A complete copy of the most current version of the project is built in a subdirectory of the current working directory. The subdirectory has the same name as the project. cvs co xxx
Checking out a specific version of a project. Same assumptions as above. Additionally, the project xxx has a tagged set of files with the tag rrr### cvs co -r rrr### xxx
Checking in cvs ci
Wrapping up project xxxx. This will delete the sandbox cvs release -d xxxx

Decoding the output of "update"

OK -- so you've run cvs update -dRP, (or any of the other update variants) and you are staring at a list of filenames with a character in front of them. Here's what the characters indicate:
status explanation
U The file was brought up-to-date with respect to the repository. This is done for any file that exists in the repository but not in your source, and for files that you haven't changed but are not the most recent versions available in the repository.
P Like U but the cvs server sends a patch instead of an entire file. Accomplishes the same thing.
A The file has been added to your private copy of the soiurces, and will be added to the source repository when you commit. This is a reminder to you that the file needs to be committed.
R The file has been removed from your private copy of the sources, and will be removed from the source repository when you run commit on the file.
M The file is modified in your working directory.
M can indicate one of two states for a file you're working on: either there were no modifications to the same file in the repository (your file remains as you last saw it); or there were modifications in the repository as well as in your copy, but they were merged successfully, without conflict, in your working directory.
C A conflict was detected while trying to merge your changes. The file in your working directory (sandbox) is nw the result of attempting to merge the two revisions; an unmodified copy of your file is also in your working directory, with the name .#file.revision where revision is the revision that your modified file started from.
? this file is in your working directory, but is not in the repository. In short, cvs will do nothing to this file. Peruse these for files that should be under cvs control.

To build a sandbox

-- assuming you have permission for a project called "GSP":
setenv CVSROOT /fs/cgd/home0/thoar/CVS.REPOS
setenv CVSUMASK 002
cvs co GSP

under development, use at your own risk Creating a repository

  1. Set some environment variables
    setenv CVSUMASK 007
  2. use the "init" command (from anywhere)
    cvs -d $CVSROOT init

File Permissions

All ',v' files are created read-only and you should not change the permission of those files. The directories inside the repository should be writable by the persons that have permission to modify the files in each directory. This normally means that you must create a UNIX group consisiting of the persons that are to edit the files in a project, and set up the repository so that it is that group that owns the directory. Note that users must also have write access to check out files, because CVS needs to create lock files.

Starting a project

Generally, the files one would want to incorporate into a project already exist. Say the files currently exist in wdir and your repository/project is going to be $CVSROOT/DumpTruck/
  1. position the current working directory
    cd wdir
  2. import the files into the project, along with a preliminary message. Note that [vendor tag] and [release tag] fill no purpose in this context but are required; one example I see uses "yoyo" and "start" for the tags. You get the picture...
    cvs import -m "Importing sources" DumpTruck [vendor tag] [release tag]
  3. Verify the files are the ones you want. "checking out" the new project, and compare the new project to the original directory.
    cd ..
    mkdir Foo
    cd Foo
    cvs co DumpTruck
    cd DumpTruck
    foreach FILE ( * )
          diff $FILE ../../wdir/$FILE
  4. If you like the project, tag the current state ...
    cvs tag DumpTruck_1_0
-- OR -- under development, use at your own risk

  1. a bit more manual, but you get to selectively add what goes into the project:
    mkdir $CVSROOT/DumpTruck
    cd wherever the code lives
    cvs co DumpTruck
    cvs add *.f90
    cvs -nq update
    cvs commit
Now, verify that it worked.

Checking out PART of a project ... i.e. Module

I have a project ($ACRONYM) with a subdirectory containing html pages that are supposed to be edited by a bunch of people. We can treat the html subdirectory as a CVS module and life gets cool in a hurry.
Those www-pages are supposed to be installed in$ACRONYM/*html.   Essentially, I want to create some sort of "link" between   $ACRONYM/doc/html/*   and   /web/web-data/$ACRONYM/*.   Since   $ACRONYM/doc/html/*   is under CVS, one solution is to duplicate THAT portion of the project (that module) into a sandbox visible to all. Everyone in the project can alter the html module without stepping on each others' toes and only when the project repository is clean do the world-visible pages get updated (I use cron.). Pretty sweet.
Now for the confusing part. The directory name of the entire project is also the obvious choice for the www-page node. I want people to go to$ACRONYM   and get the contents of the   $ACRONYM/doc/html/*   directory. How do I have a project called   $ACRONYM   and a subset of the project installed someplace also in a directory called   $ACRONYM?   (i.e. without the doc/html nodes) You have to edit the CVS administrative files, which live in a project called   CVSROOT.   To make this example more concrete, I have a project named DART.
Viola'. Now all you have to do is set up a cron job to update the www-visible repository a couple times per day and any updates are automatically installed. very sweet.

The cron part of the game is accomplished by updating your $HOME/.crontab file, which you do by

crontab -e
on whatever machine you want to be running your cron jobs (i.e. flagstaff). Remember cron uses Bourne shell syntax, and you need to pump all the output from cvs to /dev/null lest you get mail messages every time your cvs cron job runs. To recursively update the contents of your www-sandbox with cron, your crontab entry should look something like:
0 9,12,17 * * * cd /web/web-data/DART; /contrib/bin/cvs update -dR 1>/dev/null 2>&1