Zurück

Akadia Information Technology


1.   Overview

1.1  Purpose

This document introduces its reader into the subject of version control system, using the implementation of Concurrent Versions System (CVS).

1.2  Intended Audience

Anyone who is interested in software development, who is working in a development group, or who is interested in version management should read this document.

1.3  Related Documents

The listed documents are referenced below:

[CVS]

Version Management with CVS by Per Cederqvist et al

[WinCVS]

WinCvs Version 1.1 Users Guide by Don Harper

  

2.  Introduction

2.1  What is CVS ?

CVS stands for Concurrent Version System. It is a version control system that has been developed in the public domain by many people beginning in 1986. Currently, CVS is maintained by Cyclic Software and there is lots of information of their web site at http://www.cvshome.org/.

Using CVS, you can record the history of your source files (normally text files, binary files are handled with some restrictions). Instead of save every version of every file, CVS stores only the differences between the versions. CVS also helps you if you are working in a group on the same project: CVS merges the work when each developer has done its work.

Moreover, CVS allows you to isolate changes onto a separate line of development, known as a branch. When you change files on a branch, the changes do not appear on the main trunk. Later you can move the changes from one branch to another branch (or the main trunk) by merging.

2.2  Repository and Working Area

The CVS repository stores a complete copy of all the files and directories which are under version control. Normally, you never access any of the files in the repository directly. Instead, you use CVS commands to get your own copy of the files into a working directory, and then work on that copy.

CVS can access a repository by a variety of means. It might be on the local computer, or it might be on a computer across the room or across the world. Using CVS with a remote repository we talk about client/server operation. Several protocols are supported to connect to the remote repository, e.g. rsh, password authentication, GSSAPI, kerberos.

You can define several repositories if you have different development groups that work on separate projects without sharing any code. All you have to do is to specify the appropriate repository when you are starting the session.

2.3  Useful Tags

If you want to keep track of a set of revisions involving more than one file, you can use tags to give a symbolic name to a certain revision of each file. You can think of the tag as a handle. When you pull on that handle, you get all the tagged revisions.

file1   file2   file3   file4   file5

                1.1
1.1             1.2     1.1
1.2 *** 1.1 *** 1.3 *** 1.2 *** 1.1 ***   <*** tag ***>
1.3     1.2     1.4
                1.5

So it's a good idea to tag every software release, patch, or merge with its unique tag.

2.4  Multiple Developers

Often, two developers try to edit the same file simultaneously. CVS supports some solutions for this situation, e.g.

  • File locking or reserved checkouts: Only one person is allowed to edit each file at a time.
     
  • Use watches: Watched files are checked out read-only. To make them read-write (and inform others watchers) the cvs edit command is used.
     
  • Unreserved checkouts: The rarity of serious conflicts may be surprising, so often neither file locks nor watches are used. If an overlap occurs, CVS prints a warning and the resulting file includes both versions of the lines that overlap, delimited by special markers.

Note: In some cases unreserved checkouts are clearly inappropriate (e.g. if no merging tool exists).

3.  A Sample Session

To learn the most used CVS commands, we are walking through a typical work session. The commands are shown as CVS command line and over WinCVS menus. Note that the most used WinCVS commands have short cuts or context sensitive popup menus (by clicking the right mouse button).

3.1  Set-up the Session

The first thing you must set-up your CVS session. Set your environment and login to the server.

CVS commands

Set $CVSROOT for local access...

> CVSROOT=<cvs_root>
> export CVSROOT

 ... or remote access and connect to the CVS server:

> CVSROOT=:pserver:<username>@<servername>:<cvs_root>
> export CVSROOT
> cvs login

 WinCVS commands

Start your WinCVS client program. First time you must set-up your preferences.

Admin -> Preferences -> General Settings

Admin -> Preferences -> Global Settings

Admin -> Preferences -> WinCVS Settings

Then you can login to the CVS server:

Admin -> Login

Remarks

The repository's root directory <cvs_root> is defined either on the local server or on the remote server <servername>. After the successful login, you are ready to work under CVS.

3.2  Getting the Source

Next thing you must do is to get your own working copy of the source. Change to your working directory and use the checkout command to do this (option -r for read-only).

CVS commands

> cd <work_dir>
> cvs -r checkout <module>

 WinCVS commands

Create -> Checkout module ...

Choose your working area

Choose your module

Use the default settings in this example. By default, files are checked out as read-only.

  Remarks

After the successful login, the sources of <module> will be copied into your local working area <work_dir>. <module> is either a valid module name or a relative path in the repository.

If you have already checked out the sources you can update your working area with the newest checked-in files:

CVS commands

> cvs update

WinCVS commands

Select the <module> in the module tree, then the menu Modify à Update selection...

Remarks

The default directory for the update command is always the current working directory. The command updates the subdirectories recursively.

3.2  Editing the Sources

In this chapter we describe the normal way to edit a source file using reserved checkout (file locking). Change to the working directory where the file to edit exists.

CVS commands

> cd <work_subdir>
> cvs admin -l <filename>
> cvs update <filename>
> cvs edit <filename>
> vi <filename>

WinCVS commands

Select the file <filename> in the file list, then the menus

  • Trace -> Lock selection
  • Modify -> Update selection ...
  • Trace -> Edit
  • Query -> View selection or View with <default_editor>

3.4  Commit the Changes

You have decided to make a new version of the file <filename>. This will store your new file in the repository and make it available to other developers. For the undo of changes see the next chapter.

CVS commands

> cvs commit -m "<log_message>" <filename>
> cvs unedit <filename>

 WinCVS commands

Select the file <filename> in the file list, then the menu Modify -> Commit selection...

Commit settings, Enter the log message

 

Remarks

The commit command automatically unlocks the file <filename>. The unedit command is only successful if watches are in use. WinCVS also automatically makes the file read-only.

3.5 Undo the Changes

You have decided to undo the changes of the file <filename>. In this case, all the commands should be reverted. For the commit of changes see the previous chapter.

CVS commands

> cvs unedit <filename>
> cvs update <filename>
> cvs admin -u <filename>

WinCVS commands

Select the file <filename> in the file list, then the menus

  • Trace ->  Unedit selection
  • Trace -> Unlock selection

3.6  Cleaning Up

You can finish your session with the cleanup of your working area. Use the release command therefore. This command checks that all your modifications have been committed.

CVS commands

> cd <work_dir>
> cvs release -d <module>

WinCVS commands

Select the <module> in the module tree, then the menu Trace à Release selection.

Remarks

The -d option removes your working copy too. Otherwise you can remove the working area manually.

4. Advanced Commands

In this chapter some further CVS commands are described. This commands are very useful but not used in the daily business. Most of this commands have a variety of options so we recommend to look up in [CVS] as well.

4.1  Adding and Deleting Files and Directories

To add a new file to a directory, follow these steps:

  • You must have a working copy of the directory.

  • Create the new file inside your working copy of the directory.

  • Use the command cvs add <filename> to add this file to version control. For binary files use the option -kb.

  • Use the command cvs commit <filename> to actually check in the file into the repository. Other developers cannot see the file until your perform this step.

You can also use the command cvs add to add a new directory as well. Note: Unlike most other command the add command is not recursive.

New files are added, and old files disappear. But you want to be able to retrieve an exact copy of old releases everytime. 

Here is what you can do to remove a file:

  • Make sure that you have not made any uncommitted changes to the file.

  • Remove the file from your working copy of the directory (use rm or delete).

  • Use cvs remove <filename> to tell CVS that you really want to delete the file.

  • User cvs commit <filename> to actually perform the removal of the file form the repository.

Removing directories is similar to removing files: The way that you remove a directory is to remove all the files in it. You don't remove the directory itself. Instead you specify the option -P to cvs update, cvs checkout, or cvs export, which will cause CVS to remove empty directories from working directories.

4.2 Tagging

Tags are symbolic names to a certain revision of each file. We recommend to tag all software releases, patches, or merges with its unique tag.

You have two possibilities to tag: Running the cvs tag command causes CVS to select the revisions which are checked out in the current working directory. The cvs rtag command works directly on the repository contents and requires no prior checkout and does not look for a working directory.

Using the Working Directory

For the following cvs command tags the current working directory.

CVS commands

> cd <work_dir>
> cvs tag -c <tag_name> [file | directory | module]

 WinCVS commands

Select the module in the module tree or the file in the file list, then the menu Modify -> Create a tag on selection...

Remarks

You can use the option -c to check for uncommitted changes 
(locally modified files).

Using the Repository

The cvs rtag command tags the repository as of a certain date or time. This is useful to tag the latest version. rtag works directly on the repository and requires no prior checkout. This command is not supported by WinCVS. Tag the most recent revision no later than <date> ...

> cvs rtag -f -D <date> <new_tag> [file | directory | module]

... or tag those files that contain existing tag <existing_tag>

> cvs rtag -f -r <existing_tag> <new_tag> 
  [file | directory | module]

4.3 Branching and Merging

CVS allows you to isolate changes onto a separate line of development, known as a branch. When you change files on a branch, those changes do not appear on the main trunk.

Create a Branch

Again you will use the cvs tag or cvs rtag commands to create a branch. The tag command uses the current revisions in the working copy, the rtag command works directly in the repository:

> cvs tag –b <branch_tag>

... or tag those files that contain existing tag <existing_tag>

> cvs rtag -f -r <existing_tag> <branch_tag> 
  [file | directory | module]

Note that branches always get created in the repository, not in the working copy. So you must checkout the branch files to your working directory explicit:

> cvs -r checkout -r <branch_tag> <module>

or switch the working directory to a given branch with the cvs update command:

> cvs -r update -r <branch_tag> <module>

Now you can work on the branch files and commit your changes back to repository.

Merging a Branch

You can merge changes made on a branch into your working copy. The working copy could be either the main trunk or another branch.

> cvs update -j <branch_tag> [file | directory | module]

The option -j merges the changes made between up to the newest revision on that branch into your working copy. Conflicts can result from the merge operation. This conflicts should be resolved before committing the changes to the repository.

If the development continuos on that branch, you may want to merge those changes again. As recommended earlier each merged revision should be tagged in the branch. Use that tag for subsequent merges:

> cvs update -j <merge_tag> -j <branch_tag> 
  [file | directory | module]

4.4 Binary Files

The most common use for CVS is to store text files. If you are willing to give up a few of CVS' abilities (such as display differences, merging revisions), CVS can store binary files as well.

The -kb option available in some CVS commands insures that neither line ending conversion nor keyword expansion will be done. New files can be added as follows:

> cvs add -kb -m "A binary file" <filename>

Or you can use the following commands to recover the binary file:

> cvs admin -kb <filename>
> cvs update -A <filename>
> cvs commit -m "Make it binary" <filename>

4.5 Using Keywords

CVS can use a mechanism known as keyword substitution or keyword expansion to help identifying delivered files. Embedded strings of the form $keyword$ in the source file are expanded to strings of the form $keyword:value$.

This is a list of the keywords. For full explanation, please refer to [CVS].

$Author$

The login name of user who checked in the revision.

$Date$

Date and time (UTC) the revision was checked in.

$Header$

A standard header.

$Id$

Same as $Header$ (except RCS file without path).

$Name$

Tag name used to checkout this file.

$Locker$

The login name of the user who locked the revision.

$Log$

The log message supplied during commit.

$RCSfile$

The name of the RCS file without a path.

$Revision$

The revision number assigned to the revision.

$Source$

The full pathname of the RCS file.

$State$

The state assigned to the revision.

5. Administrator Tasks

In this chapter some administrator tasks are discussed. The directory $CVSROOT/CVSROOT contains some administrative files. You can edit this files in the same way that you would edit any other module: Get a working copy, edit it, and commit your changes in the normal way. When you check in an administrative file, CVS rebuilds the administrative file database.

5.1 Define Modules

The most important of the administrative files is the modules file. It defines all modules in the repository. This is not strictly necessary, but modules can be convenient in grouping together related files and directories.

Three different line formats are valid:

# key -a aliases...
# key [options] directory
# key [options] directory files...

This is a sample of modules file:

CVSROOT   CVSROOT
modules   CVSROOT modules
test      projects/test1

5.2 Security on CVS

One could write books about security issues... Here are only some recommendations.

The directory $CVSROOT/CVSROOT contains confidential information. You must control the permissions on this directory very restrictive, specially if you are using the password authenticated server.

It is possible to grant read-only access to the repository using the password authenticated server. There are two ways to do this: by inclusion and by exclusion. Inclusion means listing all users with read-only access in the $CVSROOT/CVSROOT/readers file. Exclusion means explicitly listing everyone who has write access in the $CVSROOT/CVSROOT/writers file. Please refer to the following rules:

  • If readers exists, and the user is listed in it, then the user gets read-only access.

  • If writers exists, and the user is not listed in it, then the user gets read-only access. This is true even if readers exists, and the user is not listed in it.

  • If both files exist and the user is listed in them, CVS resolves this conflict in a conservative way: such a user gets read-only access.

When authenticating a password, the server first checks for the user in the file. If it finds the user, it will use that entry for authentication, else the server can try to authenticate user name and password using the operating system's identification (fall back behaviour). Please find further information in [CVS].

5.3 Importing Sources

In a first step the files must be created in the repository. The next step is to define the module in the modules file. This step is not strictly necessary, but modules can be convenient in grouping together related files and directories.

Creating the Repository from Existing Files

You will probably already have several projects that can be put under CVS control. In this case you will use the import command:

> cd <working_dir>
> cvs import -m "Imported sources" 
  <repository_dir> <vendor_tag> <release_tag>

The files in the working directory <working_dir> are imported in the CVS repository as $CVSROOT/<repository_dir>. <repository_dir> could contain a directory structure as well.

It is a good idea to check that the permissions CVS sets on the directories inside $CVSROOT are reasonable, and that they belong to the proper groups.

If some of the files you want to import are binary, you may want to use the wrappers features or to change them manually to binary.

Creating the Directory Tree from Scratch

Create an empty directory structure and import this structure to create the corresponding directory structure in the repository. Then use the add command to add files as they appear.

Check that the permissions CVS sets on the directories inside $CVSROOT are reasonable.

Creating the Repository from Other Version Control Systems

If you have a project which you are maintaining with another version control system, you may wish to put the files from that project into CVS and preserve the revision history of the files. Here the way for RCS is shown, please see [CVS] for other systems.

This is one of the few times when it is a good idea to access the CVS repository directly: Create the appropriate directories in CVS if they do not already exit. Then copy the files in the appropriate directories in the CVS repository without changing the file name.

Note that the RCS files are not locked when you copy them into CVS.

5.4 Backing Up the Repository

For the most part it is possible to backup the repository just like any other files. However, there are a few issues to consider:

To get a consistent state of the repository, one should not use CVS during backup. To not use CVS, you might forbid logins or turn off your CVS server. Another idea is to lock CVS.

6. Examples

Starting a new project

- Go to the top of the project tree: cd /home/myproj
- cvs import -m "Initial Import into CVS" myproj akadia start

 
myproj = Name under which you will check out the project
  akadia = vendortag
  start = releasetag

The directory tree in now imported in the CVS, however you must now checking out a working copy, the current directory tree is still not a CVS working copy.

Checking out a working copy

- Go to another empty directory

Local Repository

- cvs checkout myproj 

Remote Repository

- cvs -q -d :pserver:zahn@rabbit.akadia.com:/opt/cvs-root \
  checkout myproj

You get the same as what you imported, with the addition of a subdirectory named CVS

- cd CVS (In the working CVS directory)
- ls -l

-rw-r--r-- 1 zahn dba 134 Aug 29 13:56 Entries
-rw-r--r-- 1 zahn dba   7 Aug 29 13:56 Repository
-rw-r--r-- 1 zahn dba  14 Aug 29 13:56 Root

- cat Repository
myproj

- cat Entries
/README.txt/1.1.1.1/Tue Aug 29 10:30:36 2000//
/hello.c/1.1.1.1/Tue Aug 29 10:30:36 2000//
D/a-subdir////
D/b-subdir////
D/myproj////

- cat Root
/opt/cvs-root

Making a change and find out what you or others did

Make a change on hello.c, even if nothing in the repository has changed since checkout, something in the working copy may have, and update will show that.

- cvs update

cvs update: Updating .
M hello.c
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
cvs update: Updating b-subdir
cvs update: Updating myproj

The M next to hello.c means the file has been modified. If you want a more detailed look at the changes, you can get a full report in diff format.

- cvs diff
- cvs -Q diff      
(Shorter Output)
- cvs -Q diff -c   
(Display some lines of context on either side of a change)

Commiting

The commit command send modifications to the repository.

- cvs commit -m "Error corrected in explain()"

cvs commit: Examining .
cvs commit: Examining a-subdir
cvs commit: Examining a-subdir/subsubdir
cvs commit: Examining b-subdir
cvs commit: Examining myproj
Checking in hello.c;
/opt/cvs-root/myproj/hello.c,v <-- hello.c
new revision: 1.2; previous revision: 1.1
done

Check the status of the files in the CVS repository

- cvs status

Finding out who did what (Browsing Log Messages)

- cvs log

Adding new files

Create the new file in the working CVS directory, add and commit it in CVS:

- cvs add newfile.c
  cvs server: use 'cvs commit' to add this file permanently

- cvs ci -m "Added newfile.c" newfile.c
  RCS file: /opt/cvs-root/myproj/newfile.c,v
  done
  Checking in newfile.c;
  /opt/cvs-root/myproj/newfile.c,v <-- newfile.c
  initial revision: 1.1
  done

Adding Directories

Unlike adding files, adding a new directory is done in one step:

- mkdir c-subdir
- cvs add c-subdir

  Directory /opt/cvs-root/myproj/c-subdir added to the repositor

Adding Binary Files

CVS handles CRLF correctly on textfiles, but this is not desired for binary files, therefore use the -kb option. For Textfiles you may disable the keyword expansion as well: use -ko.

cvs add -kb who
cvs ci -m "Binary File added" who

Removing Files

Removing a file is similar to adding one, except there's an extra step: You have to remove the file from the working copy first.

rm newfile.c
cvs remove newfile.c
cvs ci -m "removed newfile.c" newfile.c


Removing newfile.c;
/opt/cvs-root/myproj/newfile.c,v <-- newfile.c
new revision: delete; previous revision: 1.1
done

Removing Directories

CVS doesn't really keep directories under version control. If you want to remove a directory from a project, you first remove all the files in it, then use update -P to remove the directory from the working directory.

cd a-subdir
rm file1 file2 file3
cvs remove file1 file2 file3
cvs ci -m "Removed all files"

Now remove empty directory from working copy

cvs update -P

Bring new (empty) directories from the repository to the working copy

CVS does not automatically bring new directories from the repository into your working copy. From time to time you should run update -d, telling to bring down any new directories from the repository.

cvs update -d

All empty directories from the repository are now rebuild in the working copy.

Renaming Files

Renaming a file is equivalent to creating it under the new name and removing the old file.

mv README.txt INSTALL.txt
cvs remove README.txt
cvs add INSTALL.txt
cvs ci -m "renamed README.txt to INSTALL.txt" README.txt INSTALL.tt


Removing README.txt;
/opt/cvs-root/myproj/README.txt,v <-- README.txt
new revision: delete; previous revision: 1.2
done
RCS file: /opt/cvs-root/myproj/INSTALL.txt,v
done
Checking in INSTALL.txt;
/opt/cvs-root/myproj/INSTALL.txt,v <-- INSTALL.txt
initial revision: 1.1
done

Renaming Directories

Renaming Directories is a bit cumbersome. The best policy is to try to come up with a good layout when you initially import the project. One solution to rename one or more directories is to checkout the project, make the changes on the local working copy, delete the CVS project in the repository and import the changed project again.

cd myproj
mv a-subdir z-subdir
find . -name CVS -exec rm -rf {} \;
cd /opt/cvs-root
rm -rf myproj
cd /home/zahn/myproj
cvs import -m "Test Projekt" myproj akadia start
rm -r myproj
cvs checkout myproj

Date based Retrieval

The date-based retrieval are done by passing update the -D flag. With the -D option, update retrieves the highest revision of each file as of the given date and it will revert the files in the working copy to prior revisions if necessary. Retrieving by date is useful when the mere passage of time is your main concern.

cvs -q update -D "2000-09-14"

Event based Retrieval

Often you really want to retrieve the project as it was at the time of a specific event -- perhaps a public release, a known stable point in the software development or the addition or removal of some major feature. The method CVS offers for making such marks is known as tagging.

Setting a Tag (Snapshot):

cvs rtag Final-Release myproj

Retrieving the tagged release (Snapshot):

cvs checkout -P -r Final-Release myproj

Removing Tags (untagging)

cvs rtag -d Final-Release myproj