RHexLib Project

--- RHex Control Software Libraries ---

quick start
ESP article

Project home
CVS Access
CVS Tutorial

RHex home
Hosted by:
SourceForge Logo

CVS Tutorial

  1. Getting started

    Follow the excellent directions at http://rhex.sourceforge.net/developers.html to set up a SourceForge account, and then follow the directions at http://rhex.sourceforge.net/cvs_howto.html to enable SourceForge CVS access and set up the environment variables CVSRSH and CVSROOT. You may also want to set the environment variable "EDITOR" to "emacs" (or your favorite editor: This will be the editor CVS starts for you to write log messages, it defaults to vi).


  2. CVS Overview

    CVS is the Concurrent Versions System. In essence, there is a central repository of the code and a history of all changes made to the code, in this case managed by SourceForge. Users check local copies of the code from the repository, modify it, and then commit those changes back to the repository. Other users can "update" their local copies to propagate new changes out from the repository. Unlike most other source code control systems, CVS is designed to not use "exclusive" locks on files, i.e., when user A checks out code and makes changes, user B is still free to check out the same code and make changes. The commitment and update process is designed to merge these changes together. CVS does a credible job of merging changed files together, and is fairly conservative about warning about "conflicts," i.e., when two incompatible changes have been made to the same piece (usually line) of code.

    So, when do you commit? The simple answer is often. Do not think of a CVS commitment as setting something in stone, but rather as a lightweight bookmarking of your development. Every time you make a bug fix, or even get code to the stage of initial testing, you should commit and write log messages describing the changes you have made. The more frequently you commit, the more fine grained the "history" of your code will be and the easier it will be to track the progress of the project and see where bugs happen. For example, I frequently perform the following operation: debug a new feature on a work-bench development platform to a certain extent, commit those changes, and use CVS update to propagate the changes to my robot platform, fix the bugs that crop up when dealing with "real" hardware, and then commit those changes. In this example, I knew what I committed from the work-bench was not "working," but by using CVS I avoid the pitfalls of manual code transfer, and get a history of both my new features, and what it took to get the new features to actually work on the hardware. My only rule of thumb is to only commit things that compile.


  3. Basic CVS usage

    All CVS operations are performed through the "cvs" program. For example, to initially check out the entire RHexLib core library, you would do

    # cvs checkout RHexLib

    This will check out all files and subdirectories rooted at RHexLib in the repository. In our case, we are accessing our SourceForge maintained CVS repository via SSH, and thus every CVS operation will require you to enter your SourceForge password.

    Once you have checked out a copy of the source trees you desire, 99% of your CVS operations will involve the following three commands

       cvs update  Propagate any changes made in the repository to here
       cvs commit  Propagate any changes made here to the repository
       cvs diff  Print any changes made here since the last update

    All three of these commands with no arguments will operate recursively on all files rooted at the current directory. You can give all of these commands file or subdirectories names to restrict them to only work on those files or subdirectories.

    As the "cvs update" command progresses in propagating changes from the repository to the local source tree, it prints out various status lines for files that it is performing operations on. Each status line starts with a letter code. The codes you should be watching are "M", which means that there are changes in the local code which it has accounted for, "U" or "P" which means that updates or patches have been made to the local code due to changes in the repository, and most importantly, "C" which means there is a conflict. Any time you see a "C" you should go to that file and search for ">>>>>>>" and "<<<<<<<" which is how CVS will have delineated the conflict between the local code and the repository code. These conflicts are usually easily resolved.

    "cvs update" by itself will only check out new files, it will not check out new directories. To force cvs to checkout new directories in an update that others may have added do,

    # cvs update -d

    When you want to commit your changes to the repository, use "cvs commit." An editor should start up in which you will write a log message detailing the changes you have made. Hopefully, you are committing frequently enough that these log messages can be both detailed and short. For one-line log messages, if you want to avoid starting an editor, you can use the "-m" option, e.g.,

    # cvs commit -m "Small change" foo.cc

    I tend to use the recursive abilities of commit rather sparingly, i.e., when I have made large sweeping changes. Normally, I commit file by file (or at least directory by directory) in order to have log messages tightly coupled with pertinent files.

    "cvs diff" is probably one of the most useful commands in CVS. With it you can see exactly the changes made since the last update. You can also give it absolute dates, i.e.,

    # cvs diff -D "10/28/01"

    to see all changes made since a certain date, or you can give looser dates,

    # cvs diff -D "last week"

    One useful variant is

    # cvs diff -D now

    which will give you the difference between your local source code and the latest stuff in the repository. By default a "cvs diff" with no arguments gives you the difference between your local source code and the versions as they existed at the time of the last update. "cvs diff -D now" gives you a "preview" of the changes that will be incorporated in a "cvs update."

    The last two cvs commands that will fill out most of your repertoire are

       cvs add <filename>  Add a file or directory
       cvs remove <filename>  Remove a file or directory

    "cvs add" takes the name of the file or directory to be added to the repository. The addition will not actually be propagated to the repository until you do a cvs commit. Similarly, "cvs remove" tags a file to be removed from the repository. As a safeguard, "cvs remove" will only work on files that you have physically removed with "rm." As with additions, removals do not take effect in the repository until you do a cvs commit.


  4. Sharing a CVS local tree

    The previous section shows the standard case in which user maintain their own copies of a source tree. CVS expects this to be the standard case and "caches" the repository root in administrative files (specifically CVS/Root) in each directory of your source tree. Later invocations of CVS will, by default, ignore your CVSROOT environment variable and use this cached value.

    Unfortunately, this presents problems when multiple users are sharing the same source tree, as might be the case on board one of the robots. Since we are using SSH access to a remote repository, the name of the user who first checked out the code is embedded in the cached repository root, and every time a CVS operation is performed, the default behavior is to ask for the password of that initial user.

    To avoid this problem when using shared source trees, you should use the initial "-d" option to override CVS's default behavior, i.e.,

    # cvs -d $CVSROOT update

    will force CVS to use your CVSROOT environment variable for the root, and thus your password will be requested rather than the initial user's. I would suggest aliasing cvs to "cvs -d $CVSROOT" on platforms for which code sharing will be common.


  5. More...

    We are just scratching the surface on what CVS can do in this introduction. For more information you can look at the man page, or if you live in emacs, I find the info page on CVS very helpful (M-X info, look for CVS). In addition there are a variety of web resources available, such as

    You may especially want to check out "cvs log," for printing out the log messages, and "cvs tag," for creating and using symbolic tags (as a usage example, for RHexLib you could do "cvs diff -r rel-1-0" to see all changes made since Uluc tagged release 1.0).



This page was created by Uluc Saranli, 2001