Homepage for Eric Davis

Using a CVS Repository

CVS is a version control system that records the history of source files throughout development. Using CVS, you can easily retrieve old versions of source files to find bugs, retrieve deleted content, etc. The main CVS manual can be found at the Cyclic Software homepage. Cyclic Software supports and maintains CVS and presents a list of links to CVS manuals, GUI applications, and other related information.

This manual presents a step by step introduction to the use of the different CVS commands. It is suggested that you read through and understand what is presented in this basic manual before using the central CVS repository. A central CVS repository can be located on any public server should be accessed via the secure shell protocol (rsh is possible as well). To use this repository you must have an account on the public server.

    CVS offers a couple help commands which display the usage information. This is very useful when trying to figure out the different command line arguments used by each of the CVS commands.

    % cvs --help
    % cvs --help-commands
    % cvs <command> --help
    

  1. Environment Variables:

  2. Importing your sources for the first time:

    Each collection of sources managed by CVS is called a module. You can create a new module by importing one from scratch, from an existing collection of sources, or from an existing RCS Repository.

  3. Checking out sources:

    To checkout the sources for a specific module use the CVS checkout command. Note that the module must have already been imported to the repository.

    % cvs checkout foobar
    cvs checkout: Updating foobar
    cvs checkout: Updating foobar/bar
    U foobar/bar/y
    cvs checkout: Updating foobar/foo
    U foobar/foo/x
    
    This will create a local copy of the module in your current working directory. Now you add files to, delete files from, and edit the module sources. (See section 9 below on how to release the sources when you are done.)

  4. Updating your sources:

    When multiple developers are working on the same module, it is good practice to periodically check if the sources in the CVS repository have been modified since you last checked them out. The CVS diff and update commands are used to ensure that your local copy of the module is current. The diff command shows you which files are different and how they differ. If some files are different, then use the update command to update your local copy of the files with the new modifications.

    % cvs diff -D now foobar
    cvs diff: Diffing foobar
    cvs diff: Diffing foobar/bar
    cvs diff: Diffing foobar/foo
    
    The above diff command shows that no files have been modified and the local copy of the module is up to date. The following happens when a file has been modified by someone else and committed to the repository.
    % cvs diff -D now foobar
    cvs diff: Diffing foobar
    cvs diff: Diffing foobar/bar
    cvs diff: Diffing foobar/foo
    Index: foobar/foo/x
    ===================================================================
    RCS file: /u/wk/edavis/cvsroot/foobar/foo/x,v
    retrieving revision 1.2
    retrieving revision 1.1.1.1
    diff -r1.2 -r1.1.1.1
    1d0
    < text here
    % cvs update foobar
    cvs update: Updating foobar
    cvs update: Updating foobar/bar
    cvs update: Updating foobar/foo
    U foobar/foo/x
    
    Here the file x has been modified since the last checkout. Use the CVS update command to incorporate the new modifications from the repository to the local copy of the module. Note that there are various formats to the CVS date string (-D). Using the date now tells CVS to diff the latest module sources in the repository. If the date yesterday were used, then CVS would diff the latest revision from the previous day. Check the man page for the various correct formats.

  5. Committing your changes:

    Once you are done making any modifications to the module sources, you need to commit your changes to the CVS repository. This is done using the CVS commit command. Modify the files foobar/foo/x and foobar/bar/y and then commit them to the repository.

    % cvs commit foobar
    cvs commit: Examining foobar
    cvs commit: Examining foobar/bar
    cvs commit: Examining foobar/foo
    cvs commit: Committing foobar/bar
    Checking in foobar/bar/y;
    /u/wk/edavis/cvsroot/foobar/bar/y,v  <--  y
    new revision: 1.2; previous revision: 1.1
    done
    cvs commit: Committing foobar/foo
    Checking in foobar/foo/x;
    /u/wk/edavis/cvsroot/foobar/foo/x,v  <--  x
    new revision: 1.3; previous revision: 1.2
    done
    
    The commit command recursively traverses the foobar directory and commits any changes you have made. Here CVS showed that both the x and y files have been modified and committed to the repository.

  6. Adding and removing source files:

    A source tree is constantly changing and there is often the need to add new files and delete existing files within the directory tree. This can be accomplished for a module using the CVS add and remove commands.

    % cd foobar/foo
    % ls
    CVS/ x
    % touch z
    % ls
    CVS/ x z
    % cvs add z
    cvs add: scheduling file `z' for addition
    cvs add: use 'cvs commit' to add this file permanently
    % cd ../..
    % cvs commit foobar
    cvs commit: Examining foobar
    cvs commit: Examining foobar/bar
    cvs commit: Examining foobar/foo
    cvs commit: Committing foobar/foo
    RCS file: /u/wk/edavis/cvsroot/foobar/foo/z,v
    done
    Checking in foobar/foo/z;
    /u/wk/edavis/cvsroot/foobar/foo/z,v  <--  z
    initial revision: 1.1
    done
    
    As shown above, to add a file to the module, simply create the new file and execute the CVS add command. The add command tells CVS to import the new file when the next commit operation is performed. Now let's see what happens when a file is added and another deleted.
    % cd foobar/bar
    % ls
    CVS/ y
    % mv y a
    % ls
    CVS/ a
    % cvs remove y
    cvs remove: scheduling `y' for removal
    cvs remove: use 'cvs commit' to remove this file permanently
    % cvs add a
    cvs add: scheduling file `a' for addition
    cvs add: use 'cvs commit' to add this file permanently
    % cd ../..
    % cvs commit foobar
    cvs commit: Examining foobar
    cvs commit: Examining foobar/bar
    cvs commit: Examining foobar/foo
    cvs commit: Committing foobar/bar
    RCS file: /u/wk/edavis/cvsroot/foobar/bar/a,v
    done
    Checking in foobar/bar/a;
    /u/wk/edavis/cvsroot/foobar/bar/a,v  <--  a
    initial revision: 1.1
    done
    Removing y;
    /u/wk/edavis/cvsroot/foobar/bar/y,v  <--  y
    new revision: delete; previous revision: 1.2
    done
    
    Above is an example of how to rename a file within the repository. Simply rename the file, do a CVS remove on the old filename, do a CVS add on the new filename, and finally commit the change to the repository.

  7. Tagging sources for symbolic revisions:

    To create a snapshot of the current sources for later use, use the CVS tag command. The tag command generates a symbolic tag that is bound to each of the current revisions in your local copy of the module. Try creating the tag release-1-2 and releasing the module.

    % cvs tag -R release-1-2 foobar
    cvs tag: Tagging foobar
    cvs tag: Tagging foobar/bar
    T foobar/bar/a
    cvs tag: Tagging foobar/foo
    T foobar/foo/x
    T foobar/foo/z
    % cvs release -d foobar
    You have [0] altered files in this repository.                
    Are you sure you want to release (and delete) module `foobar': y
    
    This created the symbolic tag release-1-2 for the module. Now this tag can be specified during future checkouts. If you don't specify a symbolic tag during a checkout, the latest sources are pulled out of the repository. Now try checking out the release you just created.
    % cvs checkout -r release-1-2 foobar
    cvs checkout: Updating foobar
    cvs checkout: Updating foobar/bar
    U foobar/bar/a
    cvs checkout: Updating foobar/foo
    U foobar/foo/x
    U foobar/foo/z
    
    The above checkout command specified to grab the sources bound to the tag release-1-2. Not only can you tag the sources but you can also create a whole new branch to develop off of. This allows future development of an existing revision without disrupting the current development on the main branch. This is most useful for importing bug fixes to past revisions. Note that branches can only be rooted at a tag that has been applied to the sources. Assuming you have already checked out the release-1-2 version of the foobar module, try creating a branch called release-1-2-fix and then release the module.
    % cvs tag -b release-1-2-fix foobar
    cvs tag: Tagging foobar
    cvs tag: Tagging foobar/bar
    T foobar/bar/a
    cvs tag: Tagging foobar/foo
    T foobar/foo/x
    T foobar/foo/z
    % cvs release -d foobar
    You have [0] altered files in this repository.                
    Are you sure you want to release (and delete) module `foobar': y
    
    Here a branch has been created from the symbolic tag release-1-2 named release-1-2-fix. To check out the sources on a branch simply specify the branch tag during the checkout.
    % cvs checkout -r release-1-2-fix foobar
    cvs checkout: Updating foobar
    cvs checkout: Updating foobar/bar
    U foobar/bar/a
    cvs checkout: Updating foobar/foo
    U foobar/foo/x
    U foobar/foo/z
    % cvs release -d foobar
    You have [0] altered files in this repository.                
    Are you sure you want to release (and delete) module `foobar': y
    
    If a branch is checked out then all changes made to the module are done to the branch and future commits will not affect the main development trunk. You can also merge a branch into the main trunk using the CVS update command. Be very careful when merging two trunks as many conflicts may result. Check the CVS manual on how to merge two different development trunks.

  8. Checking the status:

    The CVS log and status commands are used to display the current status of the locally checked out module. The CVS log command will display all the logs for the file/s and the status command will display the current revision numbers and any symbolic tags that have been created. Here is the output of both the log and status commands after all the examples above have been performed.  
     

    % cvs checkout foobar
    cvs checkout: Updating foobar
    cvs checkout: Updating foobar/bar
    U foobar/bar/a
    cvs checkout: Updating foobar/foo
    U foobar/foo/x
    U foobar/foo/z
    
     
    % cvs log foobar
    cvs log: Logging foobar
    cvs log: Logging foobar/bar
    
    RCS file: /u/wk/edavis/cvsroot/foobar/bar/a,v
    Working file: foobar/bar/a
    head: 1.1
    branch:
    locks: strict
    access list:
    symbolic names:
            release-1-2-fix: 1.1.0.2
            release-1-2: 1.1
    comment leader: "# "
    keyword substitution: kv
    total revisions: 1;     selected revisions: 1
    description:
    ----------------------------
    revision 1.1
    date: 1998/05/27 19:49:09;  author: edavis;  state: Exp;
    renamed the file y to a
    =============================================================================
    
    RCS file: /u/wk/edavis/cvsroot/foobar/bar/Attic/y,v
    Working file: foobar/bar/y
    head: 1.3
    branch:
    locks: strict
    access list:
    symbolic names:
            start: 1.1.1.1
            EDAVIS: 1.1.1
    comment leader: "# "
    keyword substitution: kv
    total revisions: 4;     selected revisions: 4
    description:
    ----------------------------
    revision 1.3
    date: 1998/05/27 19:49:09;  author: edavis;  state: dead;  lines: +0 -0
    renamed the file y to a
    ----------------------------
    revision 1.2
    date: 1998/05/27 19:20:49;  author: edavis;  state: Exp;  lines: +1 -0
    changed the file y
    ----------------------------
    revision 1.1
    date: 1998/05/27 18:47:12;  author: edavis;  state: Exp;
    branches:  1.1.1;
    Initial revision
    ----------------------------
    revision 1.1.1.1
    date: 1998/05/27 18:47:12;  author: edavis;  state: Exp;  lines: +0 -0
    
    Initial import of the foobar module
    
    =============================================================================
    cvs log: Logging foobar/foo
    
    RCS file: /u/wk/edavis/cvsroot/foobar/foo/x,v
    Working file: foobar/foo/x
    head: 1.3
    branch:
    locks: strict
    access list:
    symbolic names:
            release-1-2-fix: 1.3.0.2
            release-1-2: 1.3
            start: 1.1.1.1
            EDAVIS: 1.1.1
    comment leader: "# "
    keyword substitution: kv
    total revisions: 4;     selected revisions: 4
    description:
    ----------------------------
    revision 1.3
    date: 1998/05/27 19:20:55;  author: edavis;  state: Exp;  lines: +1 -0
    changed the file y
    changed the file x
    ----------------------------
    revision 1.2
    date: 1998/05/27 18:50:38;  author: edavis;  state: Exp;  lines: +1 -0
    changed file x
    ----------------------------
    revision 1.1
    date: 1998/05/27 18:47:12;  author: edavis;  state: Exp;
    branches:  1.1.1;
    Initial revision
    ----------------------------
    revision 1.1.1.1
    date: 1998/05/27 18:47:12;  author: edavis;  state: Exp;  lines: +0 -0
    
    Initial import of the foobar module
    
    =============================================================================
    
    RCS file: /u/wk/edavis/cvsroot/foobar/foo/z,v
    Working file: foobar/foo/z
    head: 1.1
    branch:
    locks: strict
    access list:
    symbolic names:
            release-1-2-fix: 1.1.0.2
            release-1-2: 1.1
    comment leader: "# "
    keyword substitution: kv
    total revisions: 1;     selected revisions: 1
    description:
    ----------------------------
    revision 1.1
    date: 1998/05/27 19:43:14;  author: edavis;  state: Exp;
    added the file z
    =============================================================================
    
     
    % cvs status -v foobar
    cvs status: Examining foobar
    cvs status: Examining foobar/bar
    ===================================================================
    File: a                 Status: Up-to-date
    
       Working revision:    1.1     Wed May 27 19:49:09 1998
       Repository revision: 1.1     /u/wk/edavis/cvsroot/foobar/bar/a,v
       Sticky Tag:          (none)
       Sticky Date:         (none)
       Sticky Options:      (none)
    
       Existing Tags:
            release-1-2-fix                 (branch: 1.1.2)
            release-1-2                     (revision: 1.1)
    
    cvs status: Examining foobar/foo
    ===================================================================
    File: x                 Status: Up-to-date
    
       Working revision:    1.3     Wed May 27 19:20:55 1998
       Repository revision: 1.3     /u/wk/edavis/cvsroot/foobar/foo/x,v
       Sticky Tag:          (none)
       Sticky Date:         (none)
       Sticky Options:      (none)
    
       Existing Tags:
            release-1-2-fix                 (branch: 1.3.2)
            release-1-2                     (revision: 1.3)
            start                           (revision: 1.1.1.1)
            EDAVIS                          (branch: 1.1.1)
    
    ===================================================================
    File: z                 Status: Up-to-date
    
       Working revision:    1.1     Wed May 27 19:43:14 1998
       Repository revision: 1.1     /u/wk/edavis/cvsroot/foobar/foo/z,v
       Sticky Tag:          (none)
       Sticky Date:         (none)
       Sticky Options:      (none)
    
       Existing Tags:
            release-1-2-fix                 (branch: 1.1.2)
            release-1-2                     (revision: 1.1)
    

  9. When you are done:

    When you are done making your changes to the module, use the CVS release command. Since CVS does not create locks, the release command isn't necessary although it is still a good idea to use. The release command will check to ensure that no uncommitted changes exist. Modify the file foobar/foo/z and let's see what happens when the release command is executed.

    % cvs release -d foobar
    M foo/z
    You have [1] altered files in this repository.
    Are you sure you want to release (and delete) module `foobar': n
    ** `release' aborted by user choice.
    
    Oops, the file z has been edited and not committed to the repository. Better find out what has changed.
    % cvs diff foobar/foo/z
    Index: foobar/foo/z
    ===================================================================
    RCS file: /u/wk/edavis/cvsroot/foobar/foo/z,v
    retrieving revision 1.1
    diff -r1.1 z
    0a1,2
    > file changed
    > 
    
    If you don't care about the changes then simply release the local copy:
    % cvs release -d foobar
    M foo/z
    You have [1] altered files in this repository.
    Are you sure you want to release (and delete) module `foobar': y
    
    Else commit the changes and then release the local copy:
    % cvs commit foobar
    cvs commit: Examining foobar
    cvs commit: Examining foobar/bar
    cvs commit: Examining foobar/foo
    cvs commit: Committing foobar/foo
    Checking in foobar/foo/z;
    /u/wk/edavis/cvsroot/foobar/foo/z,v  <--  z
    new revision: 1.2; previous revision: 1.1
    done
    % cvs release -d foobar
    You have [0] altered files in this repository.
    Are you sure you want to release (and delete) module `foobar': y
    

  10. Administering CVSROOT:

    The CVS repository is split into two different parts. The first is $CVSROOT/CVSROOT which contains all the administrative files for CVS. The second part is all the directories which contain the actual user-defined modules. The CVSROOT administrative directory is checked out and modified just like any other module.

    % cvs chekcout CVSROOT
    cvs checkout: Updating CVSROOT
    U CVSROOT/checkoutlist
    U CVSROOT/commitinfo
    U CVSROOT/cvswrappers
    U CVSROOT/editinfo
    U CVSROOT/loginfo
    U CVSROOT/modules
    U CVSROOT/notify
    U CVSROOT/rcsinfo
    U CVSROOT/rcstemplate
    U CVSROOT/taginfo
    U CVSROOT/unwrap
    U CVSROOT/wrap
    
    These files are used for configuring the CVS repository. For a detailed description of each of these files and how to configure them, check the CVS manual. Once you are done modifying these files, you must commit the changes to the repository.
    % cvs commit CVSROOT
    cvs commit: Examining CVSROOT
    cvs commit: Committing CVSROOT
    Checking in CVSROOT/loginfo;
    /u/wk/edavis/cvsroot/CVSROOT/loginfo,v  <--  loginfo
    new revision: 1.6; previous revision: 1.5
    done
    cvs commit: Executing ''/usr/unsupported/bin/mkmodules' '/u/wk/cvs/cvsroot/CVSROOT''
    % cvs release -d CVSROOT
    You have [0] altered files in this repository.
    Are you sure you want to release (and delete) module `CVSROOT': y
    

  11. Administering User Modules:

    For example purposes, the foobar module will be shown (created from following the examples above). Here is how the directory structure for the module looks within the CVS repository.

      <username>@<wherever>:/u/wk/cvs/cvsroot/
        |
        +--CVSROOT
        |    (administrative files)
        |
        +--foobar
        |   |
        |   +--bar
        |   |   |
        |   |   +--Attic
            |   |   |
            |   |   +--y,v
            |   |
            |   +--a,v
            |
            +--foo
                |
                +--x,v
                +--z,v
    
    Within the /u/wk/cvs/cvsroot/foobar directory are history files for each file under version control. The name of the corresponding file with ',v' appended to the end. The history files contain enough information to recreate any revision of the file and a log of all commit messages and the user name of the person who commited the revision. These history files are known as RCS files because the history format is that used by the RCS version control system.

    CVS does not provide a method for specifying who can access a module. The only method of access control for files is on a pre-directory basis. All the ',v' are created read-only and the permissions should not change. The directories inside the repository should be writable by the persons that have permission to modify the files in each directory. This means that UNIX groups must be used in the repository to specify who can access, and therefore modify, the module. (Note that all CVS users must have write access to the $CVSROOT/CVSROOT/val-tags file. CVS uses this file to track the valid tag names.)

  12. CVS notifications via e-mail:

    It is useful to notify developers when changes have been made to a module in which they develop. You can configure CVS to send e-mail notifications everytime a CVS commit is performed. The e-mail message will inform what file was modified, who modified it, and include the log message. E-mail notifications for commits are specified in the $CVSROOT/CVSROOT/loginfo file. Make sure you checkout/commit the CVSROOT module when making changes. Here is a sample loginfo file:

    foobar	/usr/sbin/Mail -s %s edavis@<wherever> allison@<wherever>
    DEFAULT	(echo ""; who am i; date; cat) >> $CVSROOT/CVSROOT/commitlog
    ALL	/usr/sbin/Mail -s %s cvs-admin@nas.nasa.gov
    
    The above configuration of the loginfo file specifies the following when committing changes to the repository:
    1. When committing to module foobar, send e-mail to edavis and allison.
    2. When committing to any other module (including CVSROOT), log the necessary information to the commitlog file.
    3. When committing to any module, send e-mail to the cvs-admin list.

Eric Davis - edavis <at> insanum <dot> com