CVS: Version Control Beyond RCS

If you have tried version control, but are frustrated by the need to set explicit locks every time you want to edit a file, or perhaps dislike being unable to edit a file when other developers have already locked a file, CVS is for you.

CVS (Concurrent Versions System) is a version control system. With CVS, developers are able to review the change history of any source file, retrieve any revision of a particular file, avoid overwriting one another's changes, and keep track of releases and the file revisions that go along with them.

First, a short introduction to some of the concepts of CVS. All the sources for a project are stored in a central location called the repository. The sources in the repository are organized into modules. Typically each module represents a separate project. A module can represent any number of files and directories.

When a developer wishes to work with a particular set of sources he uses CVS to retrieve a local copy of them. This local copy can represent the most recent revision of each file or some past revision.

Typical version control systems require a user to “lock” each file he wishes to edit, preventing other developers from editing these files until the first user has committed his changes. This can be quite time consuming as developers either wait for one another to commit changes, or work simultaneously and manually merge the changes together later on. CVS solves this problem by allowing concurrent editing.

Concurrent editing allows two or more developers to work concurrently on the same files. Ordinarily, concurrent editing leads to one developer overwriting another's previously committed changes.

CVS prevents overwrites by forcing a developer to merge into his local copy any changes that have been committed to a file in the repository since he retrieved his local copy of that file. Only then can the developer commit his changes. The process is mostly automatic, but if, for instance, changes have been made to the same line of code in both the repository and the local copy, manual resolution of the conflict is necessary.

A day in the Life of...,

Let's look in on our software development team in action. Due to the confidentiality of their project, all the file names have been changed to protect the innocent. Their project is to “build a better mouse trap.”

Fixing Bugs

Fezzik, though primarily a documentation writer, (This explains why all our team's manuals are in rhyme.) does some detecting and squashing of software bugs in the course of his work. Let's watch as Fezzik fixes a critical bug in a previous release of the product.

Version 4.0 of the product was released a few months ago. Now a critical bug has been found by a very important customer. The bug must be fixed in the released version of the software, a point release made for the customer, and the fix must be merged into the working version of the software.

In investigating the problem, Fezzik has determined that the bug was introduced between the 3.3 and 4.0 versions of the software. His first step is to get a copy of the 4.0 sources. He does this with the command:

cvs checkout -r PROD_REL4-0 mousetrap

This will check out all of the directories and source code files for the entire project. The version of each source file will be the version that was included in the release with the name PROD_REL4-0, exclusive of any changes that have been to that source file since the release.

Now Fezzik has a new directory called mousetrap. In this directory are all the project sources as they were when the release 4.0 was made. Because development on the project has continued since release 4.0, Fezzik must start a new branch on the revision tree from this point. He uses the following commands:

cvs tag -b POINT_RELS_REL4-0
cvs update -r POINT_RELS_REL4-0

The revision tree will look like this:

                    |HEAD - dev for next full release
                  \ |

Fezzik could have created the branch tag before checking out the project, eliminating one step from the method he used. The following sequence would produce the same effect as above:

cvs rtag -b -r PROD_REL4-0 POINT_RELS_REL4-0 mousetrap
cvs checkout -r POINT_RELS_REL4-0

CVS has many command and option combinations. Therefore, there is often more than one way to produce the same or similar results. This flexibility allows CVS to be adapted to a wide range of development processes.

Fezzik suspects that the file cheese.c contains the bug, so he decides to view all the changes made to that file between releases 3.3 and 4.0. To do this he uses the diff command:

cvs diff -r PROD_REL3-3 cheese.c

This produces a listing of the differences between the file cheese.c in our current directory and the revision used in PROD_REL3-3. Fezzik could have specified a second revision with a

-r PROD_REL4-0

and had the same effect.

In reviewing the differences, Fezzik finds what he believes to be the bug he is looking for. He would like to clear any modifications he plans with the person who made the change, so he looks at the log file for cheese.c.

cvs log cheese.c

He sees that only Buttercup modified this file between the two releases, so he is able to talk to her about the fix. After making the fix and testing it, Fezzik is ready to commit his changes. He issues the following command from the top directory of the project:

cvs commit -m "Fixed bug #1202"

Fezzik did not specify a specific file to commit, so this command will commit all modified files in this directory and, recursively, in all of its subdirectories. Each file committed will have the message “Fixed bug #1202” added as a log message. Since this fix will be sent to a customer, Fezzik decides to tag the set of files that will be sent:

cvs tag PROD_REL4-0-1

Now Fezzik needs to create the patch file to be sent to the customer:

cvs rdiff -r PROD_REL4-0 -r PROD_REL4-0-1 mousetrap > patch4.0-4.0.1

This creates a Larry Wall format patch file which the customer can feed into the patch program to update his sources. The patches will update the customer's 4.0 sources to the new 4.0.1 sources.

Now Fezzik needs to merge the fix into the current development sources. First he updates his sources to the latest revisions on the main thread by using this command:

cvs update -A

This has the same effect as deleting the local copy of the module, and doing a new checkout of the module, thereby getting the latest revisions.

Then he has CVS automatically merge in the changes from the 4.0.1 point release with:

cvs update -j PROD_REL4-0-1

CVS will automatically merge the changes Fezzik made on the branch into these latest sources. If the merging of the two sets of sources causes conflicts, CVS will announce this. At the conflict points in the file, there will be delimited regions containing the text from both sources. These regions will need to be merged manually.

Once everything is merged, Fezzik can commit all of the changes using another commit command:

cvs commit -m "Merged in fixes in PROD_REL4-0-1"


Free Dummies Books
Continuous Engineering


  • What continuous engineering is
  • How to continuously improve complex product designs
  • How to anticipate and respond to markets and clients
  • How to get the most out of your engineering resources

Get your free book now

Sponsored by IBM

Free Dummies Books
Service Virtualization

Learn to:

  • Define service virtualization
  • Select the most beneficial services to virtualize
  • Improve your traditional approach to testing
  • Deliver higher-quality software faster

Get your free book now

Sponsored by IBM