CVS : Java Glossary

CVS (Concurrent Versions System). It lets you track changes to source code, and to maintain several different concurrent versions. Unlike PVCS (Polytron Version Control System), CVS allows more than one programmer at a time to modify a module, and it does its best to merge the changes. You can get help in the newsgroup called:

CVS Environment Variables

Before you can use CVS, you need to set up some environment variables, in autoexec.bat for Windows and in Start ⇒ Settings ⇒ Control Panel ⇒ System ⇒ Environment ⇒ User Variables for NT.
CVS Environment Variables
Environment Variable Purpose
CVSEDITOR=C:\vslick\win\vs.exe Your favourite text editor. Where the CVS repository is, usually somewhere out on the web.
HOME=W:\ The user’s home directory.
HOMEDRIVE=W: The user’s home directory
HOMEPATH=\ The user’s home directory
CVSIGNORE=VSLICK *.vtg *.vpw *.vpj directories and files you don’t want CVS to put in the repository. Note the items are separated by spaces, not commas.
In Unix, the parameters some times have lead $ signs which have some significance beween exported and unexported (global vs local).

Where CVS Squirrels Information

Look in the CVS directory of the project directory where you checked out the project. This contains crucial information. Further, in every tiny subdirectory under CVS control is yet another CVS directory. Whatever you do, don’t delete these directories or files. In it there are three text files: Entries., Repository. and Root..

The Entries. file contains a snapshot of the timestamp and version of all the local files, in that directory as of the last update.

Repository. says where this directory belongs in the repository tree, e. g. com/mindprod/welcome where com is the project name.

Root. gives the url to login to the server.

CVSHOME/.cvspass contains the url to login and the encrypted password. CVSHOME is the designated CVSHOME directory, any directory you point the CVSHOME environment variable to. CVS also of course hides information most safely in the repository on the server. Anything lost can be regenerated from the server if you are willing to fool around. If this information is lost, you can always erase and checkout from scratch. CVS acts as a great backup system, just backing up just the changes, and ignoring easily recreated files.

WinCVS also hides information in the settings directory F:\Program Files\gnu\wincvs 1.2\settings.

I have not been able to find the binary/text/ignore filter you define during import to fine tune it. Perhaps resides in the repository. Perhaps it exists only for the duration of the import.

Persuading CVS To Ignore Files

There are five places CVS learns about files that it should ignore. These would typically be such things as CVS administrative files, temporary files, Slick Edit tag files or compiled object code.
  1. The one per-repository $CVSROOT/CVSROOT/cvsignore. file contains unqualified directory names, filenames and wildcards of directories and files to exclude from CVS processing. Usually you put one wildcard, directory or file per line. You can put more than one per line if you separate them with spaces, not commas. This is on the server that holds the repository.
  2. The one per-user list in .cvsignore lives in your home directory. Don’t check your personal .cvsignore file into the repository! Note the dot comes at the beginning, not the end as for the one-per-repository cvsignore. file.
  3. Any entries in the environment variable $CVSIGNORE.
  4. Any -I options on the CVS command line.
  5. As CVS traverses through your directories, the contents of any .cvsignore files it finds. The patterns found in those files are only valid for the directory that contains them, not for any sub-directories or parent directories. This is the form of cvsignore I have had most success with.
In any of the five places listed above, a single exclamation mark ! embedded in the list of files clears the ignore list. This can be used if you want to store any file in the repository which is normally ignored by CVS. Nothing too terrible happens if you have few non-repository files uncovered by your cvsignores. They show up in your updates with a ? status.

CVS Update Result Codes

When CVS udates a file on your local drive from the repository, it lists it on the console with a one-character status code. I have explained below what these codes mean rather informally. If want the picky details, see a reference manual. My intent is to help you easily understand the general idea of what each code means.
CVS Update Result Codes
Status Code Meaning Purpose
? what? This is a file that CVS knows nothing about. The file is on your local drive, but does not correspond to anything in the repository, and is not in the list of files for CVS to ignore. It should be either:
  • deleted
  • added to the repository
  • added to one of the cvsignore files
A Added This is a new file you have recently Added to the repository, but have not yet commited. Inserting a new file into the repository is a two step process. Baud knows why.
C Conflicted A Conflict occurred when CVS attempted to merge your changes with changes from the repository. The file on your local drive contains CVS ’s bungled attempt at merging. CVS also creates a temporary backup of your unmerged changes on your local drive. You have to manually sort out the merge and eventually commit the merged changes. Don’t count on the backup hanging around for more than a day or two. If want to keep it, make a copy. The more frequenly you can commit your changes, the less trouble you will have with conflicts.
M Modified You have Modified the file recently. You have not yet committed your changes. There may or may not have been some committed changes from some other programmer successfully merged with your uncommitted changes. Unfortunately, CVS uses the same code for both possibilities. However, there are clues when CVS merges, namely a backup copy of your unmerged changes appears on your local drive, just in case CVS screwed up the merging.
P Patched Identical to U, for Update, but the change to the file was so small only the changes were sent to your machine to update it rather than the whole file.
R Removed You have told CVS to Remove a file, but you have not yet committed that removal. It is a two stage process. Baud knows why. The file no longer exists on your local drive, but it still exists in the respository. Don’t confuse removing with erasing. erasing just deletes your local copy of a file. Removing logically purges it from the central repository, though of course you could get it back from the respository if the need arose.
U Updated CVS brought your local file up to date to match the repository. This includes both new files from the repository and updates to local files that you haven’t changed but that other people have.

CVS Aliases

The cvsroot\modules. file, among other things, contain alias definitions which are lists of qualified directory and file names. You are supposed to be able to check out multiple disparate directories
cvs update -P myalias
WinCVS does not have GUI (Graphic User Interface) equivalent for this, but it lets you pass raw commands through to CVS with Admin ⇒ command line ⇒ Change Folder ⇒ Enter a CVS line command. Make sure you remember to set the correct directory for the aliases to make sense, usually near the root of the project.

CVS Error Messages

One puzzling error message you will get is:

Move away somefile it is in the way.
CVS is disturbed by the appearance of repository files it did not put there. Your best bet is simply to delete the entire directory containing the offending file by hand, and re checkout or reupdate the directory to build the necessary entries. Then you can add the files safely.


In a team project, conflict over beautification standards can lead to bloodshed.

How many spaces do you indent per level? Do the {} match the enclosing or enclosed block or half way between? Do you always use {} after if? How much whitespace do you put around around operators + - * / () []?

You must agree on a common format, at least for the repository. Otherwise

You need a common tool to beautify the source to a common standard, perhaps very compact with most of the whitespace removed. See my HtmlCompactor project for ideas.

You need beautifiers to fluff it back up again to whatever format each individual programmer likes best. You can’t very well demand he break a lifetime of habits particularly if every project has a different standard.

How CVS Works

I don’t know this for certain, but this is my current understanding of how CVS works. In the repository, on the CVS server are all the various versions/revisions. They are compactly stored as either forward or reverse deltas, the differences to apply to get to the next revision, or the differences to apply to get to the previous revision. This gives the CVS server the ability to reconstruct any version/revision.

There is a tiny cvs subdirectory inside every client directory under CVS control. In there is an Entries. file. The Entries. file contains a snapshot of the timestamp and version of all the local files that are also in the repository, in just that directory (not its children), as of the last update from the CVS server. It is:
not the current timestamp of the files.
not the date of the latest version of the files in the repository.
not the date of the file the last time you committed.
not the date you last updated the file.
but rather the date of your copy of the file the last time you did an update.

Once you understand that, everything makes sense.

When you do a checkout, CVS peppers the checkout directory with CVS directories. In the Entries. files in the directories are the timestamps of the files it gave you. The files and the Entries. file and dated with the timestamps the files were last checked in.

Let us say you don’t touch these files but came back in a week and asked for an update. In theory CVS could just send you the files all over again including any new files, but this would be time consuming. How does CVS know which files you already have up to date? If the dates of the files you have, and the dates in the locally stored Entries. file match, and that is the latest revision in the repository, there is no need to send that file again. I don’t know if CVS double checks this by computing and comparing file digest checksums. I do know it works by the client sending data to the server, not the reverse. CVS also seems to take just as along for an update no matter how recently you did one. I suspect it sends its entire list of file dates in each time, rather than just the ones that have changed since the last update.

The CVS server then sends any new and changed files. The local CVS client makes a note of the last-checked in date of the newly arrived files in the Entries file.

Now let us say that you modified a file but did not commit it yet. Then you requested an update. In this case any changes other people had merged to the file would be merged with your copy, and the date this merging happened would be recorded in the Entries. file.

Then you decided to commit your file. The CVS Client and CVS server would get together and compare the version in the repository with your version, and store the differerences in the repository. I am not sure just how clever they are about this to avoid having to transmit the entire file in either direction. The CVS client would record the timestamp this happened in the Entries. file.

CVS does not change the date on your copy of the file being committed. It might be a very old file.

What if you attempt to commit a file that has not really changed? You may have made a change and backed it out. You may have run some macro generator that produced the same results as last time. You may have used the touch utility. CVS won’t create a whole new revision in the repository for a null change. Perhaps to spank you for attempting a null commit without an update first, or perhaps just to warn you nothing happned, the CVS client does not update the Entries. file, so that the file still appears to be outstanding.

When you do an update, however, CVS will notice that the file has not really changed, and will update the Entries. to match the date of the file on the on the local machine. It will have a different date than the file in the repository, but its contents are in sync, so is no longer considered commitable. It won’t change the date on your local file to match the repository’s. It records the date of the local file of the last check in the Entries. file, not the date of the check.

I have not experimented to discover just how cleverly CVS handles these false changes. It seems much faster than if it transmitted the entire file from server to client or vice versa only to discover the files were identical. I suspect they each compute a digest on the file, or parts of the file and compare those. If the lengths and digests match, odds are very good this was a false change.

In the Way

The big remaining mystery is why does CVS sometimes complain about files that are in the way when you do an update or checkout? What is the distinction between files you have changed, new files and files that are in the way?
Situation In Entries? In Repository? In the Way?
repository file checked out
repository file checked out and then changed
new file created
repository file you copied in without first checkout or update
repository file you copied in after checkout or update

If you checkout a file, and then change it there will be an entry for it in the Entries. file. If you just put the file there yourself there won’t. There won’t be any entries for brand new files you create either until they are added. However if you copy a file in the directory rather than acquiring it through update, and it already exists in the repository, CVS can detect that. It can treat all three differently.

CVS is protecting you from thinking you are creating a new file, but which already exists in the repository. CVS insists on putting the original copy of the repository file in your directory for you and creating the entry for it. You can then change it all you like. You can add all the new files you like, so long as they don’t already exist in the repository. It does not matter that even if the file in the way exactly matches the one in the respository.

The bottom line is, you have to checkout everything to an empty directory. The rule is just before adding files, do an update to make sure there are entries matching all the files in the respository.


A CVS server it typically attached to the Internet. You don’t want just anybody coming in and looking at or modifying your code. CVS supports a number of login schemes. CVS supports varying degrees of paranoia. Typically the pserver method I mentioned earlier is for inhouse use only. On the net, you would use SSH which encrypts all transmissions as well.


Instead of typing CVS commands, you can use WinCVS, a Windows GUI, to generate the commands to the client CVS for you, or SmartCVS which is written in Java.


If you used RCS (Revision Control System) or PVCS, the predecessors to CVS, CVS is wonderful. But has it warts. In the old PVCS days a programmer intending to change a file had to lock it so that one else could make even the tiniest change to it. CVS commits are not atomic. This can be problematic. If you commit multiple files at the same time they will show up in the repository as separate commits.

Another problem is moving files around or renaming them. To CVS these have to be handled as creations of entirely new files and deletions of old ones. It does not track the renaming history.

CVS merging of changes by two different programmers is not very bright. It is befuddled by white space or method reordering. You might want to look at the competition BitKeeper or Subversion. If you want to learn about how version control will by handled in future see dynamic version control.

Subversion fixes many of the infuriating CVS problems e.g.

CMP homejump to top

available on the web at:
ClustrMaps is down

optional Replicator mirror
on local hard disk J:

Please the feedback from other visitors, or your own feedback about the site.
Contact Roedy.
Your face IP:[]
You are visitor number 61,547.