−Table of Contents
CVS Notes
Server Repository Setup
A sensible access policy is to make users members of a group (Debian uses src
), and make the CVS repository directory owner root.src, with the GUID bit set, so that CVS modules residing in that directory inherit the owner and permissions.
Also, it is easiest to set things up so that access is always by SSH, even when using the host machine. This provides good security by default.
User Environment Variables
For SSH access, the following environment variables avoid needing to specify the repository and access method each time:
CVSROOT=:ext:user@cvsserver.domain.com:/var/lib/cvs CVS_RSH=ssh
/var/lib/cvs
is the default repository directory for Debian.
Setting up a Separate CVS Lock Directory
It's preferable to set up a separate lock directory, to allow some users read-only access to modules.
cd /var/lock mkdir cvs chown root.src cvs chmod 3775 cvs
Now edit CVSROOT/config:
cvs co CVSROOT cd CVSROOT
Add/modify these lines:
# Put CVS lock files in this directory rather than directly in the repository. LockDir=/var/lock/cvs
Then
cvs ci
Read Only Access to Certain Modules
Simply using standard permissions will allow this. So to allow user bill to commit changes to files in the QMS module, but all members of src to checkout the QMS for reading:
drwxr-sr-x 3 bill src 4096 2008-10-13 16:28 QMS
Creating a New Module
cvs import
can be used to bring an existing project under CVS control. If starting with an empty module, here are three ways to create the module:
mkdir empty-dir cd empty-dir cvs import new-module-name A B
or
cvs co -d top -l . cd top mkdir new_module_name cvs add new-module-name
or directly, use the following script:
#! /bin/bash # Make new module in CVS with correct permissions and attributes BASE="/var/lib/cvs" if [ -e "${BASE}/$1" ] ; then { echo "${BASE}/$1 already exists" } else { mkdir "${BASE}/$1" chown .src "${BASE}/$1" chmod 2775 "${BASE}/$1" } fi
Adding Directories
cvs add dirname cvs add dirname/files
Adding Binary Files
cvs add -kb files
Creating a Branch
There are many ways of using (and naming) branches. Here's one way:
First tag the trunk at the branch point:
cvs tag Root-of-Validation_Tests
(Format uses hyphens for Root-of-, underscores for description).
Create branch with tag:
cvs tag -b Validation_Tests-branch
To work on the branch:
cvs up -r Validation_Tests-branch
Make changes then
cvs ci -m "Change description"
To work on the trunk:
cvs up -A
We can equally well check out our branch to a different directory:
mkdir branchdir cd branchdir cvs co -rValidation_Tests-branch
If you wish to branch from a non-tip point, initially check out the version from which to branch, e.g.
cvs up -rV01_01_02
Although there's a tag there, it's still a good idea to tag the root of the branch using the standard nomenclature.
Reverting and Merging from a Branch
By revert, we mean bring an earlier version of the codebase into the working directory (it requires a subsequent checkin to actually get the reverted files back into the repository at the current tip).
If working from the trunk, you can revert to a previous version with:
cvs up -jHEAD -jEarlier_Version_Tag
This reads as “Apply the differences between HEAD and Earlier_Version_Tag”.
If it's necessary to remove/abandon any unchecked-in local changes first, use the -C switch:
cvs up -C -jHEAD -jEarlier_Version_Tag
Due to inconsistencies in the definition of HEAD within CVS (see below), if working on a branch, revert with:
cvs up -C -jBranchname-branch -jEarlier_Version_Tag
To pull in changes from a branch tag, while working on the trunk, use
cvs up -jBranch_Tag
The single -j implies an omitted first -j which is the common ancestor of the trunk and branch development. It is possible to get into a real mess by only specifying a single -j, so it's probably a good idea to always use -j in pairs.
To merge changes from the trunk into a branch, use the same method:
cvs up -jTrunk_Tag
Again, it's safer to be specific, so:
cvs up -jRoot-of-Validation-Tests -jTrunk_Tag
Merging and Keyword Expansion
Don't use $Log$ keyword, as it makes it impossible to sensibly merge. Use $Id$ instead. Even then, conflicts will occur at that point when merging to or from a branch. Use -kk to disable keyword expansion during merging - e.g.
cvs up -kk -jBranchname-branch -jEarlier_Version_Tag cvs ci -m"Change desciption" cvs up -kkv
Note that it's necessary to check in the files before switching keyword expansion back on (-kkv), otherwise the cvs up -kkv
is ignored. This appears to be a bug.
What is HEAD?
See http://lists.gnu.org/archive/html/info-cvs/2005-09/msg00170.html
Assuming tags have been used as above, this means that HEAD is the tip of the trunk for everything apart from cvs diff
, where it is the tip of the current branch (I think).
CVS Log Reports
To restrict CVS log output to just those files that have been updated between releases, use:
cvs -Q log -SN -rV01_01_00::V01_02_00
To list change descriptions for a given release:
cvs -Q log -SN -rV01_01_00
Using Watches
Watches are useful for editing binary files (.doc etc). Straightforward locking (reserved checkouts) are not supported by CVS (there is a hack using a Perl script rcslock.pl
, but the problem with that is that because this doesn't cause files to be checked out read-only, an unsuspecting user doesn't know a file was locked by another until he goes to check in).
Watch Setup
In CVSROOT/notify
, ensure the following line is uncommented:
ALL (echo Committed to %r/%p; cat) |mail %s -s "CVS notification"
If any users have external email addresses, these need adding to the CVSROOT/users
file. The format of each line in the users file is:
CVS_USERNAME:EMAIL_ADDRESS
However, the CVSROOT/users
file does not exist in the stock CVS distribution. Because it's an administrative file, you must not only create, cvs add, and commit it in the usual way, but also add it to CVSROOT/checkoutlist so that a checked-out copy is always maintained in the repository:
# The "checkoutlist" file is used to support additional version controlled # administrative files in $CVSROOT/CVSROOT, such as template files. # # The first entry on a line is a filename which will be checked out from # the corresponding RCS file in the $CVSROOT/CVSROOT directory. # The remainder of the line is an error message to use if the file cannot # be checked out. # # File format: # # [<whitespace>]<filename>[<whitespace><error message>]<end-of-line> # # comment lines begin with '#' users Unable to check out 'users' file in CVSROOT.
Enabling Watches
Force subsequent checkouts to be read-only:
cvs watch on [files]
This step is not mandatory, but is the important one in preventing a user inadvertently wasting time on edits on a file that is already being edited.
Each user can then make themselves a watcher:
cvs watch add [files]
CVS will then send them emails as the status of files change.
Before editing files, a user should issue:
cvs edit [files]
This makes files writable. Note also that an editor becomes a temporary watcher.
When finished, a normal checkin releases the watch and changes the files back to read-only. Alternatively, if no changes where made, the user can issue:
cvs unedit [files]
To list watchers or editors:
cvs watchers cvs editors