GFDL - Geophysical Fluid Dynamics Laboratory

Guide to CVS for FMS Users and Developers

This document provides a brief description of CVS and some specifics on how it is implemented for FMS. For more details on CVS, see the CVS homepage, which contains a CVS Manual. The online slides from Amy Langenhorst’s lunchtime seminar also serve as a CVS tutorial. There are graphical user interfaces (tkcvstkdiff) available for browsing local code, as well as a web interface to the repository. Note that these interfaces are only available for users internal to GFDL.

CVS (Concurrent Versions System) is a version control system. It maintains all files as history files, whereby the complete history of all files is recorded. These files exist in a directory tree called a repository. The root of the CVS repository for FMS is /home/fms/cvs. fms is a user on the GFDL computer system, and this user id is assigned to one or more people who act as super-users of the FMS repository.

To extract files from the repository it is necessary to specify both a grouping of files and the particular historical revisions of each file. This is done with the use of CVS modules, tags and branches.

CVS Modules:

A CVS module (not to be confused with FORTRAN modules) is a grouping of history files. Although files can be extracted individually, it is usually done by specifying a CVS module. A number of modules have been defined for FMS. The module definitions are maintained by the FMS super-user and are periodically updated. For the FMS we use modules to group files needed for various modeling efforts, as well as to group subsets of such files. A description of the FMS module definitions can be found on the Module Descriptions page.

CVS Tags:

A CVS tag is a text label associated with one version of a file of source code. Although the version of each history file can be specified on a file by file basis via a revision number, it is normally done by specifying a revision tag or a branch tag. A revision tag can only be associated with one version of a file, while a branch tag indicates the newest version of the file on that branch, which may change over time (see below). A single tag can be placed on a particular revision of each history file of a module so as to define a compatible set of revisions. For FMS, we use tags to define successive releases of source code and code documentation. Note that the words “version” and “revision” may be used interchangeably in the context of CVS.

CVS Branches:

Branches are lines of development that diverge from the primary line of development. Each branch is associated with a branch tag. By specifying a branch tag, one will obtain the latest revision of each file associated with that line of development. Note that the result of obtaining code via a branch tag may change over time as the developer checks in new versions of a file. For FMS, developers normally create their own branches off of the most recent release. If a developers code is accepted the FMS super-user will create new revisions on the main line of development which are equivalent to those of the developers branch.

If you are not an FMS developer, please skip to the General Formatting of CVS Commands section.

Branch Creation Summary For FMS Developers

The FMS developers have been assigned a UNIX group (the “f” group) in order to work with the CVS repository. If you have a GFDL account and wish to join the “f” group, please send a request to the FMS super-user or  .

When checking in new versions to the repository, remember that it is important to start from the right version. For example, if you have modified galway code, you should start with a cvs-controlled directory where galway code is checked out (not fez code or havana code.) Note that if you want your code change included in the next software release, you should start with the testing version if possible. The testing tag is moved to code changes that are currently being run through regression testing by Modeling Services. The testing tag is a moving tag, and should never be used for production runs.

Using cvs status -v filename before and after each command below will inform you what cvs is doing in each command below, and will help you notice if something is going wrong. Click on the individual cvs commands below for more details on the specific commands.

To check in modified files on a new branch:

setenv CVSROOT /home/fms/cvs

cvs tag -b tagname_$user files
cvs update -r tagname_$user files
cvs ci files
  1. Use cvs tag to create a branch tag for the files or directories you wish to update. The name of the branch should have the form
    . See documentation on branch naming conventions.
  2. Move the working copy of the code over to that branch with an
    update -r command.
  3. Commit (check in) your local modifications.

To check in modified files on your existing branch:

cvs status files
#verify status=locally modified
#and sticky tag=your branch
cvs ci files
  1. To check in new changes on your existing branch, you must be working with that branch locally. Verify this with the cvs status command. The status should be “Locally Modified” or something analogous, and the “Sticky Tag” must indicate your existing branch.
  2. Commit (check in) your local modifications.

To add new files to the repository on a branch:

newgrp f

setenv CVSROOT /home/fms/cvs
cvs co directory-name
cvs tag -b tagname_$user directory-name
cvs update -r tagname_$user directory-name
#copy in the new files
cvs add directory-name/new-files
cvs ci directory-name/new-files
  1. Change to the fms group with the newgrp command.
  2. Checkout the directory to which you want to add file(s).
  3. Tag the directory-name with a previously-existing branch
    tag. The name of the branch should have the form tagname_$user.
  4. Move the working copy of the code over to that branch with an
    update -r command.
  5. Edit the new file or files, or copy them into the directory.
  6. Use cvs add to add the new file or files to the repository.
  7. Commit (check in) your local modifications.
  8. Note that if you need a new directory for your new files, it is best to ask the FMS user to create them.

To remove a file from the repository on a branch:

setenv CVSROOT /home/fms/cvs

cvs tag -b tagname_$user file
cvs update -r tagname_$user file
rm file
cvs remove file
cvs ci file
  1. Use cvs tag -b to create the branch tag for the files or directories you wish to remove. The name of the branch should have the form  tagname_$user.
  2. Move the working copy of the code over to that branch with an
    update -r command.
  3. Do a unix remove of the file in the working directory.
  4. Use cvs remove to remove the file from the repository on the branch.
  5. Commit (check in) your removal.

To add a revision tag to a file or directory:

cvs tag tagname_$user file

  1. Use cvs tag to create the revision tag for the files or directories.
    The name of the revision should have the form

To remove a revision tag from a file or directory:

cvs tag -d tagname_$user file

  1. Use cvs tag -d to delete the revision tag for the files or directories.
    You can only delete tags of the form tagname_$user.
  2. Note that this command does not remove code versions from the repository, it simply removes a revision tag from a version.
  3. Note that this command will not work to remove branch tags. You cannot remove
    branches from the repository, but if for some reason you really need to remove a
    branch tag, you can remove the name that is associated with the branch. The code versions will still be accessible with revision numbers. To remove a name associated with a branch, use cvs tag -d -B tagname_$user file. Please be very careful with this command.

General Information and Formatting of CVS Commands:

setenv CVSROOT /home/fms/cvs
Setting this environment variable tells CVS the location of the repository. You should set this before you issue any CVS commands. If the FMS repository is the only repository you regularly use, you may wish to put this line in your .cshrc.
cvs -H [command]
Use the -H option for help with any CVS command. For example, “cvs -H checkout” will print a help message for “cvs checkout”.
cvs [command] [file or directory]
This is the general format of cvs commands. For the checkout command, the directory or file paths specified must be relative to CVSROOT. For commands other than checkout, the directory or file paths specified must be relative to the current working directory.

Commands which do not modify the repository:

The following commands are for acquiring code from the FMS repository and inquiring as to the state of your local code compared with the state of the repository.

Checkout Command:

cvs checkout -r (tag, branch, or revision number) (module, directory, or file)

Example: cvs co -r damascus fms_bgrid_am2

Checkout the damascus revisions of all files comprising the AM2 module. You may use “co” as an alias for “checkout”.

Checks out (extracts) a particular revision of all files comprising a module, or recursively checkout files in the repository starting at “directory”, or checkout a single file. If checkout is done by specifying a directory then the path specified must be relative to CVSROOT. Note that “cvs co” is equivalent to “cvs checkout”. Be careful if you check out with a revision number, because CVS makes the revision number the working tag (or “sticky tag”) for the file, so CVS will have no way to know if any new revisions have been checked into the repository on the tag or branch you had been working with previously. In this case, CVS will always tell you the file is up to date when a “cvs status” command is issued.
FMS Considerations:

Two files, path_names and path_names.html are created when files are checked out of the FMS repository. The first contains a listing of relative path names to all the checked out source code files. The second is an html file containing links to all the documentation files that have been checked out. path_names is often used in combination with the make file utility mkmf.

Update Command:

cvs update -r (tag, branch, or revision number) (directory or file)

Example: cvs update -r damascus_bugfixes `/home/fms/bin/list_files_with_tag damascus_bugfixes` Update only those files that have the tag “damascus_bugfixes”, preserving the working copies of those files that do not.

Replaces or merges working files with the specified revisions, but does so without destroying modifications to working files. A critical feature of CVS is that it will never modifications that have not been checked in.This command can easily have unintended results when used by those who are not familiar with it. To avoid this one must understand how it functions in these three scenarios.

  1. When there are files specified that do not have the specified tag or branch: The working copies that have not been modified will be removed, but working copies that have been modified will not be removed.
  2. When there are files specified that do have the specified tag or branch but are modified: CVS merges or attempts to merge the local modifications with the specified revisions. When an attempted merge results in conflicts then the locally modified file is renamed and CVS replaces it with a file showing the conflicts.
  3. When a directory is specified and the corresponding directory of the repository contains contains file with the specified tag or branch that are not currently checked out: Those files will be checked out.
FMS Considerations:

When update results in new files being checked out, the paths to those files will be added to path_names and/or path_names.html. See checkout.The utility /home/fms/bin/list_files_with_tag can be used with update to prevent the removal of files that do not have the specified tag or branch.

Status Command:

cvs status (directory or file)

Example: cvs status atmos_param/strat_cloud.f90

Show status of working copy of atmos_param/strat_cloud.f90

cvs status -v atmos_param/strat_cloud.f90

Show status along with a list of all tags that exist for atmos_param/strat_cloud.f90. This list is independent of the state of the working copy.

Shows status of the working copy of one or more files. Two pieces of info that are of particular interest are the the sticky tag and the status. The sticky tag tells you what revision was checked out. A status of “Up-to-date” means that the working copy of the file is unmodified since it was checked out. A status of “Locally Modified” means that it has been modified.
FMS Considerations:

Diff Command:

cvs diff (directory or file)

Example: cvs diff strat_cloud.f90

Show updates made to the working copy of strat_cloud.f90 since it was checked out.

cvs diff -kb -rbombay strat_cloud.f90

Show differences between the working copy of strat_cloud.f90 and the bombay revision. The “-kb” argument tells cvs to ignore the differences in the keywords, such as $Id: cvsguide.html,v 1.1 2004/02/04 22:20:04 fms Exp $.

cvs diff -rdamascus -rdamascus_bugfixes atmos_coupled.f90

Show the updates made to atmos_coupled.f90 to correct a damascus bug. When given two revisions, the differences between the two revisions are calculated. In this case the state of the working copy is irrelevant.

Shows differences between the working copy of a file and the revision indicated by the sticky tag. This is useful to remind yourself of what updates you have made since checking out a file. The default form of the output is that of the unix diff command. Graphical diff utilities available for use with FMS include tkdiff and the diff available from the web CVS interface. Tkdiff accepts the same arguments as cvs diff; simply substitute “tkdiff” for “cvs diff”.
FMS Considerations:

Log Command:

cvs log (directory or file)

Example: cvs log atmos_coupled.f90

Show the revision history and log messages of atmos_coupled.f90.

cvs log -rdamascus_bugfixes atmos_coupled.f90

Show the log message of the damascus bugfix revision of atmos_coupled.f90.

Shows the revision history of a file, along with the log messages that have been entered for each revision.
FMS Considerations:

Watch Command:

cvs watch [add|remove] (directory or file)

Example: cvs watch add shared/mpp

Send an email when anyone checks in a new version of any files in shared/mpp.


cvs watch remove shared/mpp/mpp.F90

Stop sending emails when anyone checks in a new version of mpp.F90.

Allows users to monitor new versions of any file or files. Email will be sent to all “watchers” of a file when a new version of the file is checked in.
FMS Considerations:

Commands which modify the repository:

The following commands are for use by developers to add to the repository or change the state of the repostitory.

Tag Command:

cvs tag [-b] (branch name) (directory or file)

Example: cvs tag -b maroon_sak atmos_param/strat_cloud

Create a branch called “maroon_sak” off of the currently checked out revisions for every file in the directory “atmos_param/strat_cloud”.


cvs tag maroon_sak atmos_param/strat_cloud/strat_cloud.f90

Create a revision tag called “maroon_sak” on the currently checked out revision of atmos_param/strat_cloud/strat_cloud.f90.

Creates a branch for one or more files. The branch will be off the revision indicated by the sticky tag.


Note that the tag command only adds the tag to the list of valid tags for the file; it does not indicate to CVS that your local code should be on that tag or branch. You must explicitly use cvs update to move your code to the new tag or branch.
FMS Considerations:

For files in the FMS repository, branch names must contains the string “_$user”, where $user is the user’s id. For example, Steve Klein’s user id is sak. He can create a branch called “maroon_sak”, but not “maroon”. Users are only allowed to check in to branches containing their id.

Commit Command:

cvs commit (directory or file)

Example: cvs ci strat_cloud.f90

Check in a new revision of strat_cloud.f90. You may abbreviate “commit”
as “ci”, which stands for “Check In”.

Checks new modifications of files into the repository. The Sticky Tag determines to which branch the file(s) will be checked into. If the Sticky Tag is not the desired branch then cvs update must be executed to put the file on the desired branch prior to commit.
FMS Considerations:

Files must be checked into a branch. The branch name must contain the string _$user (see tag -b). Checking in files will invoke a script that brings up a log message template (in the vi editor). Although it is not enforced that the user enter a log message, it is stongly suggested.

Add Command:

cvs add (directory or file)

Example: cvs add mpp_update_domains2D.h

Put mpp_update_domains2D.h under CVS control. To be followed by: “cvs ci mpp_update_domains2D.h”.

Put a new file under CVS control that was not previously in the repository. This command does not immediately add the new file to the repository; it must be followed up with cvs ci.
FMS Considerations:

Remove Command:

cvs remove (directory or file)

Example: rm mpp_update_domains2D.h
cvs remove mpp_update_domains2D.h

Removes mpp_update_domains2D.h from the head of the CVS trunk or branch. Old versions will still be accessible with the appropriate tags. To be followed by: “cvs ci mpp_update_domains2D.h”.

Remove a file from the head of the CVS trunk or branch. The file will not be completely erased from the repository, as old versions will still be accessible with the appropriate tags. You must first do a unix remove of the file in your working directory. This command does not immediately remove the file from the repository; it must be followed up with cvs ci.
FMS Considerations:

Detailed Branch Example

As an example of how an FMS developer typically uses CVS, consider the evolution of the strat_cloud module between the bombay and calgary releases. A schematicis included showing the evolution of the relevant files. Three files are involved. strat_cloud.f90 contains Fortran code. strat_cloud.doc.html and contain documentation. The schematic shows the revision numbers of each file. Although the user is free to refer to revisions by using these numbers, there is usually no need for it. Revisions are normally referred to using tag and branch names. Revision numbers are shown here only to clarify the file evolutions.The main line of development is called the trunk, and its revision numbers take the form: 1.N Branches have more than 3 digits.

    antwerp      bombay                                                                   calgary

      1.1 ------> 1.2 --------------------------------------------------------------------> 1.3






    antwerp         calgary

      1.1 ----------> 1.2


    bombay                        calgary

     1.1  ------------------------> 1.2



      +--maroon_sak--> -->

A developer, sak, wants to modify the source code and have these modifications included in the calgary release.

  1. He first checks out the bombay release of a CVS module that includes strat_cloud.f90, and goes to that directory:
    cvs co -r bombay fms_bgrid_amip
    cd atmos_param/strat_cloud
  2. There he edits the files until he has an acceptable new versions which he wants to check in on a branch. Before checking them in, he must verify with the FMS super-user that permissions in the repository will allow him to check the files in.
  3. To check the files into the repository, he creates a branch for all three files in this directory:
    cvs tag -b maroon_sak

    Executing cvs commands like “tag” without listing specific files tags all the files in the current directory. He could have created a branch on a subset of files by explicity listing them as arguments to the tag command, as in “cvs tag -b maroon_sak strat_cloud.f90”.

  4. Prior to checking in any revisions on this branch, the “Sticky Tag” on these files must changed to the branch name. This is done with the update command:
    cvs update -r maroon_sak

    Again, a subset of files may be listed.

  5. He checks the code into the repository on the branch:
    cvs ci strat_cloud.f90

    This command invokes an editor which brings up a log message template. After entering information on this template, he quits the editor and his working copy is checked in as the first revision on his branch.

  6. He repeats this process, checking in working revisions as desired, until he arrives at what he believes to be a useful enhancement of strat_cloud.f90. Because he has modified the source code, he reviews his documentation files. He finds that needs updating but strat_cloud.doc.html does not. He works on, checking in one intermediate revision.
  7. Prior to the calgary release, he notifies the FMS super-user that he wants his branched files included in the release. His modifications are reviewed by the super_user for adherance to FSM specifications. If no further modifications are needed then the super-user checks in new revisions on the main line of development that are equivalent to those at the head of the maroon_sak branch, and puts the calgary tag on them.

Note that sak did not check in a new revision of strat_cloud.doc.html. This leaves his branch empty for this file, therefore the branch revision and the bombay revision are equivalent. There is no need to create a new revision on the trunk, and the calgary tag goes on the same revision as the bombay tag.

CVS Related Utilities


GUI interface to CVS diff that can be used to examine differences among revisions and your working copy graphically.
alias tkdiff "/home/fms/bin/tkdiff"
tkdiff [-r tag1] [-r tag2] [file]
Tkdiff accepts the same arguments as cvs diff.


GUI interface to CVS. The graphical interface to viewing the revision tree is especially useful; use “tkcvs -log file” to enter this mode.
alias tkcvs "/home/fms/bin/tkcvs"
tkcvs -log file

Web CVS:

Web Interface to the FMS repository.


List all files in a source tree that can be checked out with a given tag name.
set files = `home/fms/bin/list_files_with_tag [tag]`
echo $files  #look at the list of files
cvs update -r [tag] $files
This allows cvs to update only those files that have revisions with the given tag.


Creates a list of path names (relative to the current directory) of source tree code and documentation. Invoked during standard cvs checkouts of FMS.

Typically called from the directory containing source code via:

/home/fms/bin/list_paths *
This will create two files:
  • path_names which contains a list of paths relative to the
    source code, and
  • path_names.html which is a browseable file containing links
    to the source documentation.