MIT Information Systems

Macintosh Development

[Home] [About Us] [People] [Information Systems]
[Kerberos for Macintosh] [Applications] [Miscellaneous Documentation]


Understanding CVS

A brief introduction to the concepts of CVS

by Miro Jurisic

What is CVS?

Concurrent Versions System, or CVS, is a revision control system that


Basic ideas behind CVS

Two principal parts of a CVS system are the repository and working files. The repository resides on a CVS server, and contains history and version information about all files in the repository. Working files reside on developers' machines and only represent a particular revision of each file.

Suppose a single developer, Alice, is working on a project on her development machine. Then the picture looks like this:

Whenever she makes changes to some file in the project, Alice wants to record those changes in the repository so that there is a record of her progress later. The act of sending the changes made to working files to be incorporated into the repository is called 'committing the changes'. Alice commits her changes every day before she leaves work. After a while, the project history will grow, and the repository will contain information about past versions of all the files that are part of the project:

Thus we see the simplest form of CVS interaction: modify - commit - repeat. We will see later how this model will have to be somewhat extended later to cover for more complex scenarios.

As the project progresses, Alice may need to add or remove some files. She can do so using the CVS commands 'add' and 'remove', which schedule the files for addition or removal. However, the changes will not be propagated to the repository until Alice commits the files.

Thus we see the first important rule of CVS:

The repository is ALMOST never modified until you commit your changes

Exceptions to this rule are rare, and will be pointed out as they arise.


Getting slightly more complex: multiple developers

Some day, another developer, Bob, is assigned to work on Alice's project. They now both use CVS to work the project. The picture is now like this:

They happily work on two separate parts of the project, until some day Alice decides to modify the file called Conflict.c. Unbeknownst to her, Bob has already modified the same file, and committed his changes. Alice makes her modifications to the file, and attempts to commit her changes. However, she gets the following message from CVS:

cvs server: Up-to-date check failed for `Conflict.c'
cvs [server aborted]: correct above errors first!

Alice realizes from this cryptic message that the problem is that her working version of Conflict.c was not up-to-date before she had modified it. She needs to update her working file to the most recent version of Conflict.c from the repository, before she can commit her changes. She uses the CVS 'update' command to update her working files, and after that she happily commits her changes.

Clearly, Bob and Alice need to modify their working pattern to accommodate for the fact that they might be working on the same files from time to time. They change their use of CVS to: modify - update - commit - repeat. That way they are almost completely sure that, whenever they attempt to commit changes, they will be successful.


Fighting for control: merge conflicts

Soon, Alice and Bob discover that they were too hopeful the last time they revised their habits. One day, Alice diligently attempted to update her local files, only to get an error:

Merging differences between 1.11 and 1.12 into Conflict.c
rcsmerge: warning: conflicts during merge
cvs server: conflicts found in Conflict.c
C Conflict.c

After briefly consulting with Bob, Alice realizes that she modified the same portion of the file as Bob, and that CVS decided that their sets of changes were incompatible. However, looking inside her local version of Conflict.c, Alice finds the following:

UInt32
CountStringsInList (
    Ptr     inData)
{
<<<<<<< Conflict.c
    /* Alice: added the assertion */
    AssertIf_ (Ptr == nil);
=======
    /* Bob: ignore nil input */
    if (Ptr == nil) return;
>>>>>>> 1.12
    return *(UInt32*)inData;
}

After a brief discussion with Bob (during which he is sent to read some books about writing solid code), they agree that Alice used the correct approach. Alice modifies the file to read:

UInt32
CountStringsInList (
    Ptr     inData)
{
    /* Alice: added the assertion and educated Bob*/
    AssertIf_ (Ptr == nil);
    return *(UInt32*)inData;
}

after which she successfully commits her changes.

Having been through this, Alice and Bob learn some important facts about CVS update:

As a result, they modify they work flow to be: modify - update - resolve conflicts - commit - repeat.


Checkout: the missing link

One thing that this explanation swept under the rug was the very important question of how Alice created the initial copy of her working files. The initial act of acquiring a fresh copy of the files from the repository is called checkout, and is used only to create a complete new copy of working files on a developer's machine. Even if Alice or Bob remove some (but not all) the working files and folders on their development machines, they need to perform an update (and not checkout) to get new copies from the repository.


Conclusion

The model that has been developer above (modify - update - resolve conflicts - commit - repeat) does not require further modifications to be usable in practice. Some people might prefer to modify it slightly, but the basic ideas contained in this model always remain.

For example, Alice might choose to update her working files each morning as she comes to work, work on them until the afternoon, and then commit all her changes; of course, committing the changes will sometimes cause an up-to-date check to fail, so she will have to update her files again in order to commit, and possibly resolve some merge conflicts at that time. However, since up-to-date failures are not very frequent, and merge conflicts are even less frequent, this way of using CVS is perfectly reasonable, and does not deviate fundamentally from the modify - update - resolve conflicts - commit - repeat model.

In order to make better use of CVS and explore its additional functionality, you are encouraged to proceed with documentation on more advanced CVS topics.


Questions or comments? Send mail to macdev@mit.edu
Last updated on $Date: 2003/11/18 21:58:47 $
Last modified by $Author: smcguire $