CVS keeps a single copy of the master source modules. This copy is kept in a repository, and it contains all of the information to extract current and past software releases.
Each user has a private copy of one or more of the source modules. Initially, the user would checkout his copy of the module. Once the private copy exists, the user may add or remove files and directories to his private copy, make changes to his copy and commit them to the repository, and update his private copy to incorporate all changes committed to the repository since the last checkout, update, or commit operation.
Please do not change your default umask from 002 if you plan to use CVS.
If you want to restrict access to other non-CVS'd stuff in your account, create a ~/.private directory, set the permissions on that directory to be restrictive (e.g. 700), and put the stuff that you want to be restricted below that directory.
The CVSUMASK
environment variable is globally set on
the gloworm cluster. It will ensure that new directories in the
repository are created with shareable permissions.
cvs -d /path/to/repository init
You should check group ownership and permissions in a newly created repository, especially if you intend it to be shared. The permissions should permit group write and the set-gid bit should be set on all directories.
It is also recommended that you create a ~/.cvsrc file containing the following:
update -d -PThis automatically adds the -d (create new directories) and -P (prune empty directories) to the options for an update. My ~/.cvsrc contains:
update -d -P diff -c cvs -qwhich also produces context diffs (instead of just displaying the changed lines) and causes cvs to be quiet (i.e. printing of directories and other informational diagnostics is suppressed).
-d
<repository-location>
to specify the location of the
repository. For example, to check out a copy of Alamode,
cvs -d /home/supOO7/cvsroot checkout AlamodeThe location of the repository will be saved in your checked out copy, so you never have to specify it again.
Note that cvs supports a remote access mechanism. Assuming that you can rsh (using stock Berkeley rsh, a kerberized rsh, or a ssh client) to the remote machine, you can specify and use a remote repository via
cvs -d :ext:yergeau@gloworm:/home/supOO7/cvsroot checkout AlamodeRemote repository have slightly different semantics during commits. Rather than processing files for each directory, all modified files under the current directory and subdirectories will be committed in a single step. You will only have the opportunity to add one commit comment.
cvs updateSince the repository is shared, other users may make changes to the code in the repository. Provided that you've been put on the appropriate mailing list, you will be informed of every commit to a module. The update to your copy is based on differences between the version you previously checked out or updated and the current version in the repository. These differences are merged with your copy. Although the merge algorithms are quite advanced, it is still possible to get conflicts during a merge. If you get conflicts, you will have to hand edit the file(s) with the conflicts and decide what the update/merge should have done.
Because of the possibility of conflicts, it is best to update your copy with a few days after changes were made in the repository instead of waiting for several generations of diffs to stack up. The conflict avoidance algorithms work best with only one delta to apply.
Carefully watch the output when doing an update. It shows files that are being updated and the status of files in your private copy. The status indicators are the characters `U P A R M C ?':
It is best to update within the next few days of any changes. CVS does the best jobs of merging changes from the repository when your private copy is nearly in sync with repository version.
The `-n' flag can be used to fake an update (i.e. "cvs -n update"). CVS will show the status of the files, but will not change the local copy.
cvs commitcommits all changes to the local copy in the current directory and in any directories below it.
cvs commit fileonly commits an individual file or directory. Either form will start an editor in each directory so that a log message can be entered.
It is often useful do check the diffs before a commit so you can jog your memory and provide more meaningful comments for the log entry.
Even if you think you've only changed one file, please do an update or a diff on the whole module to make sure.
cvs add [file | directory]will schedule a file to be added to the repository on the next commit.
cvs delete [files....]will schedule a file to be removed from the repository on the next commit. The file isn't actually deleted permanently. It is just stored in an attic in the repository.
cvs diff [files...]will generate a diff of the changes you've made in your local copy. It does not show changes that will occur during an update.
cvs diff [-r rev1 | -D date1] [-r rev2 | -D date2]shows the differences between two specific revisions in the repository. See the cvs(1) manpage for information on revision and/or date specification.
As with the normal Unix diff command, `-c' can be added to generate a context diff.
cvs log [files...]shows the log comments entered for each commit
$CVSROOT/CVSROOT
directory.
Then,
cvs checkout CVSROOTEdit the
loginfo
file in the copy of
CVSROOT
, and add lines similar to
Alamode $CVSROOT/CVSROOT/log.pl %s -f $CVSROOT/CVSROOT/commitlog -m alamode-cvs@glowormfor each module. The above example will send email notification to
alamode-cvs@gloworm
whenever the module
Alamode
is cvs commit
'd. If you want a
system mail alias set up, contact action@gloworm. The
list of address for the system mail alias will be maintained by you.
cvs import modulename vendortag releasetagA checkout will create the modulename directory, and that directory will contain everything below the directory you were in when you imported the source. The vendortag and releasetag are any meaningful (or meaningless, whatever the case may be) strings.
With CVS, branches are referred to using a symbolic name called a branch "tag". Users can create new branch tags and refer to a branch tag in a checkout or update operation. There was a default branch tag ("HEAD") created when the code was imported. That tag refers to the branch used as the default branch for a checkout.
Most of the philosopy (or "conventional wisdom") surrounding the practical examples of branching that I've seen is that the mainline development branch (aka the "HEAD" branch) is the most active development line. Branches are used to
The big unanswered issue is deciding when and why to create a new branch. You don't want too many active development branches at any given time. You don't want too many branches, period.
The following discussion considers branches for entire modules. You can create/use branch tags with individual files, but I don't recommend it. CVS works best on a per-module, rather than a per-file basis.
Now onto the mechanics...
To create and use a new branch you need to
In your mainline current working copy of Prophet, run
cvs tag -b <TAG_NAME>(replace <TAG_NAME> with something meaningful and valid for a branch tag name, e.g. PRE_featureX).
Note that this does not affect your mainline current working copy of Prophet; it only affects the repository. Your mainline current working copy continues to follow the default ("HEAD") branch.
In a clean directory (not over your mainline working copy), run
cvs -d /home/prophet/cvsroot co -r <TAG_NAME> ProphetNote that the state of this checked out copy will be the state of the branch in the repository. If this is a new branch, then it will look identical to the copy of the mainline ("HEAD") branch in the repository.
At this point, you can make changes, add/delete files, commit, etc. in either the mainline ("HEAD") branch or another branch. The committed changes will not appear the other branch. I.e. commits in one branch will not be update'd into another branch.
All commits to every branch of a module will continue to be broadcast to the mailing list, regardless of what branch they affect. I may be able to further filter some of the non-default branch commits to a limited mailing list (or just ignore mailing them).
At some point, you will want to merge changes into another branch. With cvs, this is done with a "join" update followed by a commit. For example, to merge committed changes from a "PRE_featureX" branch into the mainline, you would cd into your mainline copy, then
mainline/Module/src% cvs update -j PRE_featureXAssuming that there were no conflicts in the merge ("join update"), you would then compile/test Prophet. If the testing is successful, then you could commit the merged changes (into the mainline branch). To merge changes from the mainline branch into another branch, just do a join update from the "HEAD" branch.
featureX/Module/src% cvs update -j HEADAs always, the repository version of the branch is not changed until you commit.
cvs edit <file>(or use the emacs function vc-toggle-read-only which is bound to C-x C-q)
To "unedit" a file, I recommend deleting the file and updating instead of the "cvs unedit" command. The unedit command has been known to move an older version into place, retaining the modification date of the older version. Since the modification date is old, make may not properly rebuild/replace the object, if needed.
To view who is editing files
cvs editors [<file>]