Code management with CVS
| About | Setup | New Project | Working | Adding new files | Removing old files | Branches and Tags |

Code management with CVS


About CVS

CVS (older docs here and yet older docs there) is a public domain (GNU) software package which allows multiple developers to work on a single software project. CVS handles source code version control and file merging as well as transaction monitoring (i.e. it reports to others automatically when sources have been changed). In contrast to other systems (RCS, SCCS) it allows concurrent developments even on the same source file.
CVS uses a central repository containing the source files organized in modules. Each software project is such a module and each module is assigned a directory in the central repository. Examples in biophysics are the TRAX track simulation, the therapy planning TRiP, the gd graphics program, and possibly many others (SATAN,...).
CVS doesn't use locking, instead it provides a copy of an entire project to each developer. When changed files are to be stored back into the central repository CVS detects conflicting versions from different developers. He who comes late has to update his sources with the versions stored centrally. CVS is able to perform an automatic code merging and complains if this is impossible. To achieve all this CVS stores a couple of administrative files in a special subdirectory CVSROOT in addition to the user defined projects.
CVS requires the central repository to be pointed to by the environment variable $CVSROOT. For the members of the bio group this variable is set automatically in the login profile. Additionally, most CVS commands allow to specify this location directly. All members of the bio group have read access but only members of the biodev group have write access to this pretty holy area.
Note:
all write accesses to the $CVSROOT area must be executed under the process group biodev. This is ensured by means of the s-bit set in all relevant directories.

Note:
The CVS installation active in Biophysics has adapted versions of

    $CVSROOT/CVSROOT/loginfo.sh
    $CVSROOT/CVSROOT/commitinfo.sh
    
to allow special actions after check-in, e.g. automatic generation of readable (and compilable) source copies.

Setting up a repository

This is normally needed only once and for all, because many projects can be held in one repository. One proceeds as follows:
    mkdir <repository>
    export CVSROOT=<repository> # include this in some central profile
    cvsinit
    
This procedure is already completed for the biophysics.

Setting up a new project

This is normally needed only once at the beginning of a new project. It goes as follows:
  1. In your home directory:
        cvs co CVSROOT
        cd CVSROOT
        
  2. There's a file called modules. Add a line like
        <project-name> <dir> 
        
    where <project-name> is the name of your software project and <dir> is the name of a directory in $CVSROOT which will contain all files belonging to the project. Normally one would choose the same name for both.
    Example:
        TRK             TRK
        
  3. Inform CVS about the changes:
        cvs ci 
        
  4. Then you have to populate the repository with the new files.

Setting up a new project, the dirty way

    in your local directory
  1.    mkdir CVS
    
  2. create three files Entries, Repository, Root
  3. Then:
       mkdir $CVSROOT/<dir>
       cvs add <file-list>
       cvs ci
    

Working with CVS controlled source files

As follows:
  1. This step is only needed once to establish a complete local working copy of a module (aka project). It works recursively.
       cd ~
       cvs co <project-name>
       
    creates a directory <project-name> in your home directory with all (!) sources of the given project. If you want another destination directory you use
       cvs co -d <other-dir> <project-name>
       
    Example:
       cvs co -d TRKFUDGE TRK 
       
    checks out the complete TRK project to some alternative fudge directory.
    One may also check out a certain release, for example to obtain a snapshot of some earlier version of the sources:
       cvs co -d TRiP98-my2kx -r pre2kx TRiP98
       
    This requires the existence of the release tag pre2kx.

  2. Go to the local working directory. Edit, compile, link, test (!!). If complete, checkin (commit) the changed files to the central repository.
       cd <project-name>
       ... edit etc. 
       cvs ci <file>
       ... rebuild libraries and executables in repository
       
    Example:
       cd TRK 
       vi trkvol.c
       ... 
       cvs ci trkvol.c 
       make -f trk.make  # rebuild object library libtrk.a
       make -f trk.m     # rebuild executable trk
       
    CVS will store the source file into the central repository, but keeps a local copy in your working directory. If commit fails because someone else has checked in the same file with his/her changes goto the next step.

  3. You use
       cvs update <file>
       
    to bring your local files in sync with the central repository. It might then be necessary to repeat the previous step.
Note: Don't forget to rebuild the associated libraries and executables. Typically there's some makefile <project-name>.make to rebuild the object library lib<project-name>.a and a make file <project-name>.m to rebuild the complete executable. (e.g. trk.make, libtrk.a, trk.m).

Adding new files

To add newly edited source files you use the following sequence
   cd  <project-name>
   cvs add <file>
   cvs ci  <file>
   
As above, you have to rebuild the associated library and the executable.
Normally only text files should be stored in the repository. However, it is possible to store also binary files like executables and data files under CVS control. In such cases extreme care has to be taken that no CVS/RCS keywords are inserted in the binary files. One has to apply an extra keyword -kb when files are added:
   cd  <project-name>
   cvs add -kb <file>
   cvs ci  <file>
   

Removing old files

To remove obsolete source files you use the following sequence
   cd  <project-name>
   rm         <file>
   cvs remove <file>
   cvs ci     <file>
   
As above, you have to rebuild the associated library and the executable.

Branches and Tags

Releases

It is a good idea to assign a unique release tag to all files once a software is considered a well-tested public release, e.g.:
   cvs rtag r9712 <project-name>                  # by last revision
   cvs rtag -D 2012-02-01 pre1107 TRiP98  # by date
will assign unique release tags r9712 and pre1107, respectively to all files (recursively through all directories) of the project. Note that release tags must start with a letter. One can get rid of them by e.g.:
cvs rtag -d wrongtag <project-name>

Branches

Creating

You establish the begin of a branch called e.g. b9801 with one of the two possibilities:
   cvs rtag -b -r r9712       b9801 <project-name>
   cvs rtag -b -D "31 Dec 97" b9801 <project-name>
The branch b9801 consists of all files with the tag r9712 in the first case or all revisions not older than "31-Dec-97" in the second case.

Working

To work with that branch you checkout:
   cvs co -d <project-name>9801 -r b9801 <project-name>
Updates and check-ins now only occur within the branch and the local working copies, the "main trunk" remains unaffected !

Merging

You merge branches into the main trunk:
   cvs co -d <project-name>merge -j b9801 <project-name>
will first merge the differences between main trunk and branch recorded in the repository into a merging directory. Usually conflicts have to be resolved manually, then
   cd  <project-name>merge
   cvs ci
will store back the results into the repository. Note that the branch still exists.

New project from a branch

This is not directly described in the docs.
I used the following procedure (example):
  1. checkout the last version into an import directory
       cvs co -d <newproject-name>IMPORT -r b9801 <project-name>
    
    Remove all CVS directories in <newproject-name>IMPORT
  2. re-import (using <newproject-name>) as described in Setting up a new project.

Trouble Shooting

Reference copy manually

Sometimes a check-in fails to create the readable reference copy. Here's an example how to create these copies manually, for branch beam and all sources in project directory TRiP98/TEST/RBE:
cvs co -r beam -d $CVSROOT/../TRiP98BEAM/TEST/RBE TRiP98/TEST/RBE
Other example:
cvs co -d $CVSROOT/../TRiP98 TRiP98
will produce reference copies for the entire TRiP98 project.
In any case, check the log messages for conflicting files which should be removed before.

Can't check-in due to editor troubles

CVS uses emacs as its default editor for entering comments on check-in.
This may fail due to mis-configured emacs or faulty X session. In this case one may revert to simpler editors like nedit or even vi:
export CVSEDITOR=vi

| About | Setup | New Project | Working | Adding new files | Removing old files |
Last updated: M.Kraemer, 7-Feb-2012