this summary written by Geoff Berry gcb@cs.duke.edu
What is CVS?
From the man page:
cvs - Concurrent Versions System
DESCRIPTION
cvs is a front end to the rcs(1) revision control system
which extends the notion of revision control from a collec-
tion of files in a single directory to a hierarchical col-
lection of directories consisting of revision controlled
files. These directories and files can be combined together
to form a software release. cvs provides the functions
necessary to manage these software releases and to control
the concurrent editing of source files among multiple
software developers.
Setting Up A Repository
What Is A Repository?
For a group to use CVS a single CVS repository must be created.
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, 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.
Specifying A Repository
To allow the CVS commands to work on your group's repository, you
must set the $CVSROOT environment variable to the
absolute path to the root of the repository. For example if the
repository for my group was in my home directory in the
subdirectory cps108/Repository I would add the
following line to my .cshrc file (don't forget to
source the .cshrc file so the changes take effect):
setenv CVSROOT ~/cps108/Repository
If the repository is in another user's directory hiearchy you cannot use the
~ abbreviation, you'll need to specify the complete
path, e.g.,
setenv CVSROOT /afs/acpub/users/g/c/gcb/cps108/Repository
Creating A Repository
Now that the location of the repository has been specified
in the environment, it must
be created. Note that this is only done once, NOT for each
project. To create a repository, type:
cvs init
This will create an empty repository in the directory specified by
$CVSROOT. If you get an error message then you
probably forgot to source your new .cshrc file and the
shell can't find the $CVSROOT environment variable.
File Permissions in the Repository
The directories inside the repository should be writable by the
persons that have permission to modify the files in each
directory. This normally means that you must create a group
consisting of the persons that are to edit the files in a project,
and set up the repository so that it is that group that owns the
directory.
Creating Groups on AFS (acpub)
On the acpub system running AFS, individual users can create
groups. Use the pts command to do this. To create a
group (done by the user with login-id peter, for example):
pts creategroup peter:hyperwag
To add users to the group:
pts adduser paul peter:hyperwag
pts adduser mary peter:hyperwag
Now the directory in the repository can be made writable
by the group, peter does this since he owns the directory. If the
name of the project is `hyperwag' peter would type:
fs setacl ${CVSROOT}/hyperwag peter:hyperwag write
Now everyone in the group `peter:hyperwag' can access and modify
files in the `hyperwag' subdirectory of the repository. (Note,
if you get an "undefined variable" when you type the line above
try without the braces, i.e., $CVSROOT/hyperwag instead of
${CVSROOT}/hyperwag.
Using CVS
Starting a Project From a Tree of Files
When you begin using CVS, you will probably already have several
projects that can be put under CVS control. In these cases the
easiest way is to use the `import' command. An example is
probably the easiest way to explain how to use it. If the files
you want to install in CVS reside in ~/cps108/hyperwag , and you
want them to appear in the repository as `$CVSROOT/hyperwag',
you can do this:
prompt> cd ~/cps108/hyperwag
prompt> cvs import -m "Imported sources" hyperwag Group7 start
Unless you supply a log message with the `-m' flag, CVS starts an
editor and prompts for a message. The string `Group7' is a
"vendor tag", and `start' is a "release tag". They may fill no
purpose in this context, but since CVS requires them they must be
present.
You can now verify that it worked, and remove your original source
directory. In the dialog below, the user moves the
hyperwag directory to hyperwag.orig then check
out the project named hyperwag (the hyperwag.orig
directory is a backup in case something didn't work properly).
prompt> cd ..
prompt> mv hyperwag hyperwag.orig
prompt> cvs checkout hyperwag
prompt> ls hyperwag
prompt> rm -r hyperwag.orig
Erasing the original sources is a good idea, to make sure that you
do not accidentally edit them in `hyperwag.orig', bypassing CVS.
Of course, it would be wise to make sure that you have a backup of
the sources before you remove them.
Starting a Project From Scratch
For a new project, the easiest thing to do is probably to create
an empty directory structure in your working directory
( e.g. ~/cps108 ), like this:
prompt> mkdir hyperwag
prompt> mkdir hyperwag/doc
prompt> mkdir hyperwag/testing
After that, you use the `import' command to create the
corresponding (empty) directory structure inside the repository:
prompt> cd hyperwag
prompt> cvs import -m "Created directory structure" hyperwag Group7 start
Then, use `add' to add files (and new directories) as needed.
$ cvs add Reader.cc Writer.cc
Getting the Source
The first thing you must do is to get your own working copy of the
source for hyperwag. For this, you use the checkout
command:
cvs checkout hyperwag
This will create a new directory called `hyperwag' and populate it
with the source files (e.g. `Reader.cc' and `Writer.cc').
You start your favorite editor, hack away at `Reader.cc', and a
couple of hours later you have added support for a new
week-at-glance language to the Reader hiearchy.
Committing Your Changes
When you have checked that hyperwag is still compilable you
decide to make a new version of `Reader.cc'.
cvs commit Reader.cc
CVS starts an editor, to allow you to enter a log message. You
type in "Added support for new language.", save the temporary
file, and exit the editor.
The environment variable $CVSEDITOR determines which
editor is started. If $CVSEDITOR is not set, then if
the environment variable $EDITOR is set, it will be
used. If both $CVSEDITOR and $EDITOR are
not set then the editor defaults to vi. If you want
to avoid the overhead of starting an editor you can specify the
log message on the command line using the `-m' flag instead, like
this:
cvs commit -m "Added support for new language." Reader.cc
Bringing a File Up to Date
When you want to update or merge a file, use the
update command. For files that are not up to date
this is roughly equivalent to a checkout command: the
newest revision of the file is extracted from the repository and
put in your working copy of the module.
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.
For instance, imagine that you checked out revision 1.4 and
started editing it. In the meantime someone else committed
revision 1.5, and shortly after that revision 1.6. If you run
update on the file now, CVS will incorporate all
changes between revision 1.4 and 1.6 into your file.
If any of the changes between 1.4 and 1.6 were made too close to
any of the changes you have made, a "conflict" occurs. In such
cases a warning is printed, and the resulting file includes both
versions of the lines that overlap, delimited by special markers.
Handling Conflicts
Suppose revision 1.4 of `Reader.cc' contains this:
Reader::Reader( const string & filename )
{
myFilename = filename;
}
Revision 1.6 of `Reader.cc' contains this:
Reader::Reader( const string & filename )
: myFilename( filename )
{
}
Your working copy of `Reader.cc', based on revision 1.4, contains
this before you run cvs update:
#include
Reader::Reader( const string & filename )
{
myFilename = fullPath( filename );
}
You run cvs update:
prompt> cvs update Reader.cc
RCS file: ~cps108/Repository/hyperwag/Reader.cc,v
retrieving revision 1.4
retrieving revision 1.6
Merging differences between 1.4 and 1.6 into Reader.cc
rcsmerge warning: overlaps during merge
cvs update: conflicts found in Reader.cc
C Reader.cc
CVS tells you that there were some conflicts. Your original
working file is saved unmodified in `.#Reader.cc.1.4'. The new
version of `Reader.cc' contains this:
#include
Reader::Reader( const string & filename )
: myFilename( filename )
{
<<<<<<< Reader.cc
myFilename = fullPath( filename );
=======
>>>>>>> 1.6
}
Note how all non-overlapping modifications are incorporated in
your working copy, and that the overlapping section is clearly
marked with `<<<<<<<', `=======' and `>>>>>>>'.
You resolve the conflict by editing the file, removing the markers
and the erroneous line. Suppose you end up with this file:
#include
Reader::Reader( const string & filename )
: myFilename( fullPath( filename ) )
{
}
You can now go ahead and commit this as revision 1.7.
prompt> cvs commit -m "Changed constructor to use initializer list." Reader.cc
Checking in Reader.cc;
~/cps108/Repository/hyperwag/Reader.cc,v <-- Reader.cc
new revision: 1.7; previous revision: 1.6
done
CVS Keywords
You can include CVS keywords in source (and object) code so that the
revision number, author, date, etc. is always shown in code (and in
object files). A keyword is typed with case matching exactly as
shown below between two dollar signs $$, e.g., $Date$. When a file
is checked out, the keyword is replaced by its value, e.g., "January
20, 1998". Keywords are typically put in comments as shown below.
#include
// Demo program for CVS
// $Id$
int main()
{
cout << "Hello World" << endl;
}
When the file is checked out (for the first time) the source is as
follows:
#include
// Demo program for CVS
// $Id: foo.cc,v 1.1 1997/01/20 22:58:41 ola Exp $
int main()
{
cout << "Hello World" << endl;
}
To include CVS information in object files, create a dummy string
variable in your source code that will generate a string in the
compiled code.
static const char CVSid[] = $Id$;
For More Information
To find out anything else you could possibly want to know about CVS
consult the CVS info pages. The can be accessed via emacs through
the following commands:
M-x info
g
(/usr/pkg/cvs-1.9/share/info/cvs.info)Top
This document contains text from the CVS info pages, the man page
cvs(1), and is based on the cps108
RCS tutorial availible on the
cps108 web page.
Owen L. Astrachan
Last modified: Fri Feb 13 11:42:22 EST 1998