Notes on Using CVS

$Date: 2002/04/16 17:04:51 $
$Revision: 1.2 $

This document is a reminder of how to use CVS. It is not a complete tutorial on CVS. If you have forgotten some terms, you may find the glossary of value.

Getting Started

cvssetup.sh will guide you though the setup of a local CVS repository. This sets up projects in your personal repository which is typically in the directory $HOME/dev/$USER (e.g. ~tpg/dev/tpg) which is just a symbolic link to .../fusion/$USER/dev/$USER (e.g. .../fusion/tpg/dev/tpg). You should only invoke this once. The CVSROOT is /group/boehnke/cvsroot. Most times you will not need to know this, but depending on how you decide to work with CVS, there might be times when you'll need to know this path.

Initially you will want to put files into CVS. Copy the files into your a local repository, add and then commit the files. Thereafter, you will be in a cycle of edit and commit for files in CVS.

Adding CVS Directories

You may (and should) create subdirectories in your local repository. It can be confusing to tell if a directory is under CVS control or not. Simply using the 'mkdir' command does not automatically put a directory under CVS control. A simple way to determine if a directory is a CVS directory is to look for a subdirectory 'CVS'. If you see a CVS subdirectory, then you know the parent is a CVS local repository.

To make a directory in your local repository, do the following:

  1. cd ~/dev/$USER
  2. mkdir mydir
  3. Invoke tkcvs from the command line
  4. Navigate through the directories until you see your new directory (mydir in this case). Now you need to ADD this to CVS.
  5. Select the directory (e.g. mydir) and 'cvs add' it - click on the button labelled '+" at the bottom of the screen. Now when you list the contents of that directory you should see a CVS subdirectory in mydir.

Adding Files in the Local Repository

You may create files in your local repository just as you would in any Unix directory (mv, cp, with your editor etc.). Note, however, just creating the file in your local repository does not mean the file is under CVS control. As with directories you need to do a CVS add of the file.

Unlike directories, you can't directly tell if a file is in CVS or not. The easiest way is to use a tool like tkcvs where you can see the CVS status of the file. Once the file exists in the local repository, here are two easy ways to add files to CVS.

  1. Using tkcvs
  2. Using cvsedit.pl
  3. Using cvscheckout.pl

CVS Reasons as Comments

The CVS activity for a file may be automatically recorded in your source code. This is done by including comments in your source like this:

In a SAS program, include the line:
   
    *  $Log: cvsnotes.html,v $
    *  Revision 1.2  2002/04/16 17:04:51  tpg
    *  Add details about cvscheckoutversion.sh
    *
    *  Revision 1.1  2002/02/05 15:06:33  tpg
    *  Moved from bin/doc
    *
    *  Revision 1.6  2001/10/29 19:30:18  tpg
    *  Add title
    *
    *  Revision 1.5  2001/10/09 20:03:27  ppwhite
    *  cvsetup changed to cvssetup under Getting Started
    *
    *  Revision 1.4  2001/09/18 18:32:18  tpg
    *  Add cvscheckout.pl and copy2prod.sh
    *;

In a Unix script, include the line:

    # $Log: cvsnotes.html,v $
    # Revision 1.2  2002/04/16 17:04:51  tpg
    # Add details about cvscheckoutversion.sh
    #
    # Revision 1.1  2002/02/05 15:06:33  tpg
    # Moved from bin/doc
    #
    # Revision 1.6  2001/10/29 19:30:18  tpg
    # Add title
    #
    # Revision 1.5  2001/10/09 20:03:27  ppwhite
    # cvsetup changed to cvssetup under Getting Started
    #
    # Revision 1.4  2001/09/18 18:32:18  tpg
    # Add cvscheckout.pl and copy2prod.sh
    #

Comparing Different Versions of Files

Sometimes you want to know what's changed in a file. Try this:

  1. Invoke tkcvs from the command line
  2. Navigate through the directories until you find the file of interest. Select this file.
  3. From the menu, select File -> Log Browse (or click on the button with the small tree at the bottom of the screen).
  4. Enter the versions you are interested in comparing (typically the last version in CVS and the previous version).
  5. Select the button with the delta (yellow triangle) to invoke tkdiff.

Obtain a Previous Version of a File

Occaisionally you want a copy of a file from some point in the past. Try this:

  1. If you've made changes to the file interest, save this file in your local repository as it will be overlaid by this sequence.
  2. Invoke tkcvs from the command line
  3. Navigate through the directories until you find the file of interest. Select this file.
  4. From the menu, select File -> Update with Options.
  5. Select the checkbox "Update (-r)..." and provide the version as "Tag Name". Select the OK button.
  6. The file of interest is now in your local repository with a new name "filename.tagname" (i.e. 'mysas.sas.1.23').

To get back the latest version of the file from CVS, repeat this sequence, but select the checkbox "Update local files..." and select the OK button.

Tools

You'll find these commands useful:

copy2prod.sh is the command used to copy a file in your CVS local repository to it's production directory (e.g. /group/boehnke/bin). This is simply managed by creating a file copy2prod.txt in each CVS directory. This file maintains a list of files in this directory and the correct destination production directory. See more details with the command 'copy2prod.sh -h'.
cvs is the command used to interface with CVS repositories. It can be pretty complex to use, but typically you only use a couple of commands or other scripts will invoke this. cvs --help will remind you of the syntax and, of course, man cvs will tell you lots more.
cvscheckout.pl is a script to help you checkout subdirectories from the fusion project. You can also find this on the User Defined menu of tkcvs.
cvscheckoutversion.sh is a script to checkout a particular version of a file. Enter something like 'cvscheckoutversion.sh mysas.sas 1.5' and it will create the file 'mysas.sas.1.5'. This avoids the so-called 'sticky' tag problems in CVS. If you follow the instructions in the previous section ('Obtain a Previous Version of a File'), this is the command that will be invoked. You may use that interface or issue this command at the command line interface.
cvsedit.pl is a script to help automate the edit/commit cycle. This can even be used to add files to a repository. The script simply invokes your editor (specified by the environment variable $EDITOR, or defaults to nedit and when that is done, asks if you want to commit the file.
cvssetup.sh is a script to set up projects in your local repository, typically $HOME/dev/$USER and $HOME/dev/fusion.
tkcvs provides a graphical interface to CVS. Most importantly it shows your CVS directories and the CVS status of each file. You can invoke your editor (specified by the environment variable $EDITOR, or defaults to nedit) as well as adding, updating and commiting files. Typically all you need do is invoke the command "tkcvs". You may, however, force tkcvs to start in a specific directory with a command like "tkcvs -dir dirname".
tkdiff provides a graphical display to show the differences between two files. Command syntaxt is "tkdiff file1 file2".

Special Cases

Regular files are all treated the same way - edit and commit in a cycle. However, there are a couple of conditions might be a little surprising.

Directories
You can and should create subdirectories in your local repository. Just remember to do a CVS add of the directory. Unlike adding files, do you should not commit the new directory.

Update Merges
CVS allows more than one person to work on a file. A merge occurs when two people both make changes to the same file in their own local repository and then commit the file. There will be no problem for the first person to commit.

When the second person attempts to commit (or update his copy), CVS will attempt to merge the CVS master file with the modified version of the second person. Many times this will cause no problem because the modifications by the two people were in different parts of the file.

You will see a message telling you a merge was successful in this case. Just because the changes were in different parts of the file does not mean there is no problem. TkCVS and TkDiff can help you figure out exactly what changed.

Update Collisions
This is simply a case where and update merge occurred, but both people made changes in the same place in the file. CVS will merge in both changes and mark them with the string "<<<<<<<<". It will be very obvious where this happens. You'll need to figure out what should change, make the changes and commit the corrected file. Fortunately, this does not happen very often.

CVS Keyword Substitution

When you do a commit, CVS will scan your source file for certain strings and modify your source as it is being checked-in. This is typically done to include reasons in comments or to automatically manage a version string.

Note that only the part between the two '$' is changed. This allows you set program variables to the string. In Perl one could do:

 my $version = '$Revision:$';
 
   which gets changed each time a commit is made to something like
   
 my $version = '$Revision: 1.2 $';

You may find these keywords of interest:

$Date:$
This will be changed each time to the date of the commit and will result in a string like:
  $Date: 2002/04/16 17:04:51 $
$Id:$
This will be changed each time to the CVS filename, date and userid of the person doing the commit and will result in a string like:
  $Id: cvsnotes.html,v 1.2 2002/04/16 17:04:51 tpg Exp $
$Log:$
This will result in the CVS filename, followed by the version number, date and userid on the next line and the reason (provided at commit time) on following lines: For example:
#  $Log:$

  would become

#  $Log: cvsnotes.html,v $
#  Revision 1.2  2001/08/01 16:13:30  tpg
#  Correct various flags to force use of gw file
#
$Revision:$
This will be changed each time to the version of the CVS filename and will result in a string like:
  $Revision: 1.2 $

Copying CVS Files to Production

As you work with files in the project fusion you will eventually come to the point where you wish to copy the finished files to our production directories (e.g. /group/boehnke/fusion/Template). The script copy2prod.sh will help with this.

The convention we have established is to that you will create a file copy2prod.txt in each subdirectory where you have files you wish to copy into production. For instance, consider this fictitious directory, fusion/findgene. This directory might contain files like:

  findgene.c
  findgene.h
  Makefile
  run_findgene.sh
  copy2prod.txt

and copy2prod.txt might contain:

  #   Put findgene into production
  findgene    /group/boehnke/bin
  run_findgene.sh   /group/boehnke/bin

Most times you will invoke copy2prod.sh from cvsedit.pl or tkcvs (see the User Defined menu). For instance in tkcvs, you would select run_findgene.sh and the select User Defined -> Copy_to_Production. This will invoke the script which will find run_findgene.sh in the copy2prod.txt in the same directory and copy it to /group/boehnke/bin. There's no magic going on here, you must have write authority to the target directory.

Don't forget to also add and commit your copy2prod.txt file to CVS so someone who follows you can also copy a file into production.

CVS from the Command Line

For the person who insists on using the commands directly, you certainly may. You just need to know a little more. All of these commands will require you to specify the CVS master repository. You may do this by adding "-d /group/boehnke/cvsroot" immediately after the command "cvs" (e.g. cvs -d /group/boehnke/cvsroot cvscommand). Alternatively, you may set the environment variable CVSROOT to /group/boehnke/cvsroot.

The following commands are the ones you'll most like want to know about. In each case you should first CD into your local repository and issue the command.

cvs add name Use this command to add 'filename' to the repository for this project. "Name" can, of course, be a list of files. If "name" is not a directory you should follow this with a cvs commit command.
cvs checkout name Use this command to get a working copy of a file, directory or set of files from cvsroot to the current working directory. "Name" should start with the name of the project, like:
  cvs checkout fusion/bin/process/dopanelchecking.pl
  
will create three subdirectories and one file in the current working directory.
cvs commit name Use this command to get a "check-in" a file into cvsroot. You will be prompted to enter a reason code.
cvs log name Use this command to see all the activity for particular file.
cvs update name Use this command to synchronize the file/files/directory in your local repository. This may delete, add or modify files in your local repository. You will always want to include several options like this: cvs -d /group/boehnke/cvsroot update -A -d -P directory-name

Glossary

commit
is a CVS command to modify cvsroot with your version of a file. It will require you to enter a reason code and also increments the revision number. This is sometimes referred to as 'checkin'.

checkout
is a CVS command to fetch files from the master repository to your local repository. Use this the first time you fetch files and update thereafter.

import
is a CVS action to automatically add and commit a tree of files into cvsroot. This can be tricky as if requires you to get the relative paths of the files correct. We discourage using import. A safer mode is to add and commit the files.

local repository
is a directory where your local copy of CVS is kept. You may have more than one of these, but typically this is to be found in $HOME/dev/$USER.

master repository
is a directory where all the CVS data is kept. This is commonly known as cvsroot.

merge
is a CVS action to update a file where you have already made a change and automatically add, update or delete lines from the file in cvsroot.

project
is a collection of CVS data. There will usually be a project name which matches your uniqid. There will be others which match logical collections of FUSION public data.

reason code
is one or more lines describing why a change was made to a file.

revision
is a numbered string CVS associates with each change in a file. The numbering scheme has its own conventions which you should not attempt to control or use as the basis for anything - except to be able to identify a particular version of a file. This is not the same concept as a release of a file or set of files.

update
is a CVS command to synchronize the data in your local repository with that in cvsroot. It will remove files which have been removed from cvsroot, modify files that have been changed and create new copies of newly created files.