CVS: Client-Server Version Control LG #66

Overview

CVS is a version control system. Using it, you can record the history of your source files. CVS helps if you are part of a group of people working on the same project, sharing the same code. Several developers can work on the same project remotely using CVS’s client-server model in which the code exists on a central server and each programmer get the source on his local machine from the CVS server (checkout) and save it back on the CVS server (checkin) after development. Each time a programmer checks in his new code into the CVS server, the difference is saved as a new version rather than overwriting the previous version. This allows the server to recreate any previous version upon request, although by default it distributes the latest version.

This article explains how to use CVS in client-server mode and get the most out of it.

Getting CVS

You can find CVS in your Linux distribution or get the source from http://www.cvshome.org/downloads.html

The home page for CVS is http://www.cvshome.org.

The repository

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. When you’ve finished a set of changes, you check (or commit) them back into the repository. The repository then contains the changes which you have made, as well as recording exactly what you changed, when you changed it, and other such information.

Creating a Repository
To create a repository, run the CVS init command. It will set up an empty repository in the CVS root specified in the usual way .

 
cvs -d /usr/local/cvsroot init

Here /usr/local/cvsroot will become the repository.

CVSROOT environment variable

Set the CVSROOT environment variable in your shell startup script. For instance, in ~/.bashrc:

 
$ export CVSROOT=:pserver:username@foo.com:/usr/local/cvsroot 

Backing up the Repository
There are a few issues to consider when backing up the repository:

  • One should either not use CVS during the backup, or have the backup program lock CVS while doing the backup.
  • To lock CVS, you would create `#cvs.rfl’ lock files in each repository directory.

Remote Repositories
Your working copy of the sources can be on a different machine than the repository. Using CVS in this manner is known as client/server operation.

Setting up the server:
Put the following entry in /etc/inted.conf on server:

 
2401 stream tcp nowait root /usr/local/bin/cvs cvs -f --allow-root=/usr/cvsroot pserver

If your inetd wants a symbolic service name instead of a raw port number, then put this in `/etc/services’:

 
cvspserver2401/tcp

and put cvspserver instead of 2401 in `inetd.conf’.

After making you changes, send a HUP signal to inetd.

Password authentication for remote repository
For remote password authentication put a file `$CVSROOT/CVSROOT/passwd’ . The file will look like:

 
anonymous:
kapil:1sOp854gDF3DY
melissa:tGX1fS8sun6rY:pubcvs

The password is in Unix encrypted form. The first line in the example will grant access to any CVS client attempting to authenticate as user anonymous, no matter what password they use. The second and third lines will grant access to kapil if he supplies his respective plaintext passwords.

The third will grant access to melissa if she supplies the correct password, but her CVS operations will actually run on the server side under the system user pubcvs.

Note: CVS can be configured not to check the UNIX real passwd file i.e /etc/passwd for CVS authentication by setting SystemAuth=no in the CVS `config’ file ($CVSROOT/CVSROOT/config).

Using the client with password authentication

You have to login to CVS server for the first time:

 
cvs -d :pserver:kapil@foo.com:/usr/local/cvsroot login

The you can use all the commands of CVS on the remote machine:

 
cvs -d :pserver:kapil@foo.com:/usr/local/cvsroot checkout someproj

Read only repository access It is possible to grant read-only repository access to people using the password-authenticated server. There are two ways to specify read-only access for a user: by inclusion, and by exclusion.

READ  Interview with Google's Sergey Brin LG #59

« Inclusion » means listing the user in the `$CVSROOT/CVSROOT/readers’ file, which is simply a newline-separated list of users. Here is a sample `readers’ file:

 
kapil
yogesh
john

(Don’t forget the newline after the last user.)

« Exclusion » means listing everyone who should have write access. If the file    $CVSROOT/CVSROOT/writers exists, then only those users listed in it will have write access, and everyone else will have read-only access. The `writers’ file has the same format as the `readers’ file.

Setting up the files in repository
If the files you want to install in CVS reside in `someproj’, and you want them to appear in the repository as `$CVSROOT/someproj’, you can do this:

 
$ cd someproj
$ cvs import -m "Imported sources" someproj vendor 
rel1-1

Here The string `vendor’ is a vendor tag, and `rel1-1′ is a release tag.

CVS locks in repository
Any file in the repository with a name starting with `#cvs.rfl.’ is a read lock. Any file in the repository with a name starting with `#cvs.wfl’ is a write lock. The directory `#cvs.lock’ serves as a master lock. That means one must obtain this lock first before creating any of the other locks.

To obtain a read lock, first create the `#cvs.lock’ directory. If it fails because the directory already existed, wait for a while and try again. After obtaining the `#cvs.lock’ lock, create a file whose name is `#cvs.rfl.’ followed by information of your choice (for example, hostname and process identification number). Then remove the `#cvs.lock’ directory to release the master lock. Then proceed with reading the repository. When you are done, remove the `#cvs.rfl’ file to release the read lock.

To obtain a write lock, first create the `#cvs.lock’ directory, as with a read lock. Then check that there are no files whose names start with `#cvs.rfl.’. If there are, remove `#cvs.lock’, wait for a while, and try again. If there are no readers, then create a file whose name is `#cvs.wfl’ followed by information of your choice (for example, hostname and process identification number). Hang on to the `#cvs.lock’ lock. Proceed with writing the repository. When you are done, first remove the `#cvs.wfl’ file and then the `#cvs.lock’ directory.

Symbolic revisions using tags in CVS
The release number of final software releases are different from revisions in CVS. The revision numbers might change for several times between two releases.You can use the tag command to give a symbolic name to a certain revision of a file.

Change to the working directory and issue the following command for tagging:

 
$ cvs tag rel1-1 file.c

This command will tag the file « file.c » as release 1.1

 
$ cvs tag rel1-1 .

This command will tag all the files under current directory recursively as revision 1.1

You can use the `-v’ flag to the status command to see all tags that a file has, and which revision numbers they represent by issuing the following command:

 
$ cvs status -v file.c

Now you can checkout any revision of a module by using the following command:

 
$ cvs checkout -r rel1-1 module1

here « module1 » is the name of the module. The -r flag with checkout option makes it easy to retrieve the sources that make up revision 1.1 of the module `module1′ at any time in the future.

Multiple Developers

File status
The cvs status command gives a status about the states of the files. You can get a status of the file by:

 
$ cvs status [options] files

Bringing a file up to date
When you want to update or merge a file, use the update command. This brings into your working copy the changes others have recently committed. Your modifications to a file are never lost when you use update. If no newer revision exists, running update has no effect. If you have edited the file, and a newer revision is available, CVS will merge all changes into your working copy.

READ  Mail2News Mini-Howto: Establishing the mail aliases

Resolving Conflicts

If two people simultaneously make changes to different parts of the same file, CVS is smart enough to merge the changes itself. But if two people make changes to the same part of a file, CVS cannot tell what the final result is supposed to be, so it gives up and wines, « Conflict! » Conflicts arise when one developer commits a change and a second developer, without running cvs update to receive the first developer’s change, tries to commit his own incompatible change. Resolving changes can take hours or even days. In this section, I will explain how to resolve source conflicts.

When you enter the cvs commit command to automatically upload all the files you have changed or added to a project, the CVS repository server may inform you that your locally-edited files are not up-to-date with the server or that you need to manually merge one or more files with newer versions that have already been uploaded to the repository by some other developer. Here’s a typical warning message that occurred during a CVS commit process:

 
$ cvs commit
cvs commit: Examining .
cvs commit: Up-to-date check failed for `andy.htm' 
cvs commit: Up-to-date check failed for `sample.htm' 
cvs commit: Up-to-date check failed for `index.htm' 
...
cvs [commit aborted]: correct above errors first!

You can use the cvs update command to update your local project copy with the latest changes in the cvs repository. To update your entire working copy of the site, open a command prompt, change to the directory containing the project you’re developing, and issue the command:

 
$ cvs update

This will update and automatically merge every file that has changed since you last copied over new files from the CVS repository. Line-by-line updates to individual text files (such as HTML files) can often be handled automatically. CVS will list for you any files that require your attention for manual editing and merging.

Automatic merge example:
You are editing some project file called « index.html » locally and when you try to commit that file to CVS repository then CVS will give you the following error:

 
$ cvs commit index.html
cvs commit: Up-to-date check failed for `index.html' 
cvs [commit aborted]: correct above errors first!

This happens because there is a newer version of the same file on the CVS repository. You should use cvs update command to get the latest version from the CVS repository onto your local machine:

 
$ cvs update index.html
RCS file: /usr/local/cvsroot/index.html,v
retrieving revision 1.4
retrieving revision 1.5
Merging differences between 1.4 and 1.5 into index.html 
M index.htm

After the automatic merge process you should check the merged copy to check if it is working properly. When you are satisfied with the local copy of « index.html » file then you can commit it to CVS:

 
$ cvs commit index.htm
Checking in index.htm;
/usr/local/cvsroot/index.htm,v > File2.txt
$ cvs commit

Removing files To remove files from a site, you run the cvs remove command on the desired filenames in your working copy. As a « safeguard », cvs remove will not work if the working copies of your files still exist.

Syntax:  $ cvs remove [options] files

$ cvs remove file.html
cvs server: file `file.html' still in working directory
cvs server: 1 file exists; remove it first
$

To get around this, you may use the -f option with the cvs remove command or remove the file first and then execute the cvs remove command.

$ cvs remove -f oldfile.html
cvs server: scheduling `oldfile.html' for removal
cvs server: use 'cvs commit' to remove this file permanently
$ cvs commit
 
Or
$ rm File3.txt
$ cvs remove File3.txt
$ cvs commit
 

This will not delete the actual file from the CVS server yet; it simply makes a note to tell the server to remove these files the next time you commit your working copy of the project.
 

Removing directories The way that you remove a directory is to remove all the files in it. You don’t remove the directory itself: there’s no way to do that. Instead you specify the `-P’ option to cvs update or cvs checkout, which will cause CVS to remove empty directories from working directories. (Note that cvs export always removes empty directories.) Note that `-P’ is implied by the `-r’ or `-D’ options of checkout. This way CVS will be able to correctly create the directory or not depending on whether the particular version

READ  Framebuffer HOWTO: Contributors

you are checking out contains any files in that directory.

Creating the directory structure from number of files in the CVS repository
This cvs import command is used to put several projects in cvs repository.

$ cd source here source is the files that you want to put in cvs repository.
$ cvs import -m "Test Import" My_Files Revision1 start
The string
‘Revision1’

is a vendor tag, and
`start'

is a release tag. “My_Files” is the name of directory in cvs repository. The –m option is to put log message.

Get the working copy of files from CVS

Okay, now we want to download these files into a Working directory. When we checkout a package from cvs, it will create a directory for us. The parameter « My_Files » that we specified when we uploaded the files into cvs will be the name of

the directory created for us when cvs downloads the package for us.

Now we need to get the cvs package.

 
$ cvs checkout My_Files

Downloading updates that other people make

If you have downloaded a package from a repository that someone else is maintaining, if you wish to download all the changes, then execute the following command,

 
$ cvs update -dP

The « d » creates any directories that are or are missing. The « P » removes any directories that were deleted from the repository.

Viewing the difference
You can easily see the difference between two file using cvs.

 
$ cd project
$ cvs diff index.html

This command runs diff to compare the version of `index.html’ that you checked out with your working copy.  Here « project » is the name of the local project directory.

 
$ cvs diff -r 1.20 -r 1.21 hello.c

This command will show the difference between two versions of same file.

The annotate Command
With annotate, you can see who was the last person to touch each line of a file, and at what revision they touched it. It gives you more information than the history command:

 
$cvs annotate

View logs

 
$ cvs log -r 1.21 hello.c

This will show you the logs for hello.c version 1.21

Other tools and add-ons to CVS

Henner Zeller’s CVSweb 
It has a feature of browsing the CVS repository by web browser and even shows the latest revision and log message for each file. It presents you with a web-based interface to browse any and all of the sites and projects you manage by  CVS. You can get it from http://stud.fh-heilbronn.de/~zeller/cgi/cvsweb.cgi/

Martin Cleaver’s CVSweb
 It features capabilities for file upload as well as file browsing of CVS repository. You can get this software from http://sourceforge.net/projects/cvswebclient/

LinCVS
A CVS GUI client for Linux. It provides nice features and easy to use. You can get it from: http://www.lincvs.org/

WinCVS
A CVS GUI client for Windows. It has many good features and I will recommend this software for Windows clients. You can get it from http://www.cvsgui.org/download.html

More Information

CVS Manual : http://www.cvshome.org/docs/manual/cvs.html

CVS Mailing lists: http://www.cvshome.org/communication.html

note-8046740Kapil Sharma

Kapil is a Linux/Unix and Internet security consultant. He has been working on various Linux/Unix systems and Internet Security for over three years. He maintains a web site (http://linux4biz.net) for providing free as well as commercial support for web, Linux and Unix solutions.

Copyright © 2001, Kapil Sharma.
Copying license http://www.linuxgazette.com/copying.html
Published in Issue 66 of Linux Gazette, May 2001