====== 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: # # [][] # # 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