Mu2e Home
CVS Intro & Cheat Sheet

Simplest Use Pattern: Rarely Recommended

The simplest use pattern of cvs has four steps and it makes sense only if you are sure that no one else is modifying the same files that you intend to modify:

  1. Check out the files you need.
  2. Modify some or all of these files.
  3. Create some new files. There are tricks to adding new directories: see below.
  4. Edit the release notes file.
  5. Commit your new files and changed files to the repository.

Before the commit, the changes you made are local to your working copy. After the commit, anyone who checks out the code will get your changes.

The reason that this pattern is not recommended is that the "c" in cvs stands for "concurrent"; cvs allows many people to check out the same files and work on them in parallel. Therefore the following scenario is possible:

  1. You check out a file.
  2. Someone else checks out the same file;
  3. The other person changes the file and commits it back to the repository.
  4. You change the file and commit.
  5. The commit will fail with a message that your changes conflict with previously committed changes.

If you have changed many files it is possible that some commits will succeed while others fail.

In general this will leave the code base in broken state and it is your job to fix it promptly.

The Recommended Use Pattern

The recommended pattern is:

  1. Check out the files you need.
  2. Modify some or all of these files.
  3. Create some new files.
  4. Make a backup of your work.
  5. Use cvs status and cvs update to check for and merge in changes made by others. Resolve any conflicts this creates. See below.
  6. One final check to ensure that changes made by someone else do not conflict at run-time with changes you made. This step is not needed if cvs update did not modify you working copy.
  7. Edit the release notes file.
  8. Commit your changes and delete your backups.

Checking for And Resolving Conflicts

It is possible that, after you checked out your code, someone else committed changes to cvs. It is your job to check for this situation, to make sure that your changes do not conflict with the other person's changes and, if they do, to resolve the conflicts. Remember that cvs only knows about conflicts of the form "two people changed the same line"; it cannot tell that the combination of change by you and a change by some else, perhaps in a different file, will cause incorrect program behaviour.

Cvs has a variety of tools to help you manage this situation. The cvs history command will tell you who has made what changes recently. The cvs status command will tell you which files are up to date, which files have possible conflicts, and so on. And cvs update will try to bring your working copy up to date with the head of the repository. These three commands are discussed in more detail below.

The emacs editor has a powerful and convenient interface to cvs status. To use cvs status by hand, do the following:

How to Recover from a Failed Commit

If your commit fails because of conflicts, it is your job to fix it promptly. Very likely the cvs HEAD will be in a broken state until you fix it.

In some cases the fix will be easy. Just edit your working copy, find the problem and fix it. Usually, however, you will need to do more work. The following are some suggestions.

First, you should make a backup of the current state of your work. You can use cvs history to see who else has recently worked on the offending file; they may have useful advice. You can use cvs diff to compare the current HEAD with the version the other person started from; this will identify what the other person did. You can use cvs diff to compare your working copy with the HEAD; this will show the conflicts plus your other changes that are not conflicts. As a last resort, you can delete the offending file from your working copy and re-checkout the HEAD of that file; after that you can, by hand, merge your changes into the HEAD (this is why it is recommended to make a backup before you start the commit process).

Zombie Directories in your checked out code

Suppose that you have a checked out copy of the code on which you are working. Then you are told that a directory has been deleted in the cvs head. You might expect the following command to remove the directory if you execute it in your top level working directory:

cvs update -PdA
If the only files under that directory are files managed by cvs, then this command will do exactly what you expect - it will remove the entire directory tree rooted at the deleted directory.

However the mu2e build system, scons, interferes with this. When you run scons, it leaves object files ( ending in .os ) in the same directory as the corresponding source files (ending in .cc). Therefore the action of cvs update with the above options will be to:

A typical result is that the .os files remain, along with all of the directories on the path to them. If this happens, verify that the directory tree rooted at the removed directory does not contain files that you care about. If it does, move those files elsewhere. Then, from the top level of your working directory,

 /bin/rm -r -i <directory_name>
 /bin/rm -r -i lib/libmu2e_<directory_name>*

If you are sure that all is OK, then use ^C to interrupt the command and reissue it without the -i. The second step removes the libraries created from the deleted code.

An alternative is always to do the following when you expect directories to be removed by a cvs update:

find <directory_name> -name \*.os -exec rm {} \;
/bin/rm -r -i lib/libmu2e_<directory_name>*
cvs update -PdA
This removes all .os files and .so files before doing the update; so there will be empty directories for the update to remove.

This sort of behaviour is common to most code management systems, which never touch files that are not under their management.

CVS Cheat Sheet