This chapter is for people who have never used CVS, and perhaps have never used version control software before.
If you are already familiar with CVS and are just trying to learn a particular feature or remember a certain command, you can probably skip everything here.
CVS is a version control system. Using it, you can record the history of your source files.
For example, bugs sometimes creep in when software is modified, and you might not detect the bug until a long time after you make the modification. With CVS, you can easily retrieve old versions to see exactly which change caused the bug. This can sometimes be a big help.
You could of course save every version of every file you have ever created. This would however waste an enormous amount of disk space. CVS stores all the versions of a file in a single file in a clever way that only stores the differences between versions.
CVS also helps you if you are part of a group of people working on the same project. It is all too easy to overwrite each others' changes unless you are extremely careful. Some editors, like GNU Emacs, try to make sure that the same file is never modified by two people at the same time. Unfortunately, if someone is using another editor, that safeguard will not work. CVS solves this problem by insulating the different developers from each other. Every developer works in his own directory, and CVS merges the work when each developer is done.
CVS started out as a bunch of shell scripts written by
Dick Grune, posted to the newsgroup
comp.sources.unix
in the volume 6
release of December, 1986. While no actual code from
these shell scripts is present in the current version
of CVS much of the CVS conflict resolution algorithms
come from them.
In April, 1989, Brian Berliner designed and coded CVS. Jeff Polk later helped Brian with the design of the CVS module and vendor branch support.
You can get CVS in a variety of ways, including free download from the internet. For more information on downloading CVS and other CVS topics, see:
http://www.cvshome.org/ http://www.loria.fr/~molli/cvs-index.html
There is a mailing list, known as info-cvs
,
devoted to CVS. To subscribe or
unsubscribe
write to
info-cvs-request@gnu.org
.
If you prefer a usenet group, the right
group is comp.software.config-mgmt
which is for
CVS discussions (along with other configuration
management systems). In the future, it might be
possible to create a
comp.software.config-mgmt.cvs
, but probably only
if there is sufficient CVS traffic on
comp.software.config-mgmt
.
You can also subscribe to the bug-cvs mailing list, described in more detail in section Dealing with bugs in CVS or this manual. To subscribe send mail to bug-cvs-request@gnu.org.
CVS can do a lot of things for you, but it does not try to be everything for everyone.
VPATH
in `Makefile's, etc.), you can
arrange your disk usage however you like.
But you have to remember that any such system is
a lot of work to construct and maintain. CVS does
not address the issues involved.
Of course, you should place the tools created to
support such a build system (scripts, `Makefile's,
etc) under CVS.
Figuring out what files need to be rebuilt when
something changes is, again, something to be handled
outside the scope of CVS. One traditional
approach is to use make
for building, and use
some automated tool for generating the dependencies which
make
uses.
See section How your build system interacts with CVS, for more information on doing builds
in conjunction with CVS.
diff3
) command.
CVS does not claim to help at all in figuring out
non-textual or distributed conflicts in program logic.
For example: Say you change the arguments to function
X
defined in file `A'. At the same time,
someone edits file `B', adding new calls to
function X
using the old arguments. You are
outside the realm of CVS's competence.
Acquire the habit of reading specs and talking to your
peers.
cvs commit
operation, CVS then forgets that those files were
checked in together, and the fact that they have the
same log message is the only thing tying them
together. Keeping a GNU style `ChangeLog'
can help somewhat.
Another aspect of change control, in some systems, is
the ability to keep track of the status of each
change. Some changes have been written by a developer,
others have been reviewed by a second developer, and so
on. Generally, the way to do this with CVS is to
generate a diff (using cvs diff
or diff
)
and email it to someone who can then apply it using the
patch
utility. This is very flexible, but
depends on mechanisms outside CVS to make sure
nothing falls through the cracks.
commitinfo
file. I haven't
heard a lot about projects trying to do that or whether
there are subtle gotchas, however.
As a way of introducing CVS, we'll go through a typical work-session using CVS. The first thing to understand is that CVS stores all files in a centralized repository (see section The Repository); this section assumes that a repository is set up.
Suppose you are working on a simple compiler. The source consists of a handful of C files and a `Makefile'. The compiler is called `tc' (Trivial Compiler), and the repository is set up so that there is a module called `tc'.
The first thing you must do is to get your own working copy of the
source for `tc'. For this, you use the checkout
command:
$ cvs checkout tc
This will create a new directory called `tc' and populate it with the source files.
$ cd tc $ ls CVS Makefile backend.c driver.c frontend.c parser.c
The `CVS' directory is used internally by CVS. Normally, you should not modify or remove any of the files in it.
You start your favorite editor, hack away at `backend.c', and a couple of hours later you have added an optimization pass to the compiler. A note to RCS and SCCS users: There is no need to lock the files that you want to edit. See section Multiple developers, for an explanation.
When you have checked that the compiler is still compilable you decide to make a new version of `backend.c'. This will store your new `backend.c' in the repository and make it available to anyone else who is using that same repository.
$ cvs commit backend.c
CVS starts an editor, to allow you to enter a log message. You type in "Added an optimization pass.", 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 there is a default
which will vary with your operating system, for example
vi
for unix or notepad
for Windows
NT/95.
In addition, CVS checks the $VISUAL
environment
variable. Opinions vary on whether this behavior is desirable and
whether future releases of CVS should check $VISUAL
or
ignore it. You will be OK either way if you make sure that
$VISUAL
is either unset or set to the same thing as
$EDITOR
.
When CVS starts the editor, it includes a list of
files which are modified. For the CVS client,
this list is based on comparing the modification time
of the file against the modification time that the file
had when it was last gotten or updated. Therefore, if
a file's modification time has changed but its contents
have not, it will show up as modified. The simplest
way to handle this is simply not to worry about it--if
you proceed with the commit CVS will detect that
the contents are not modified and treat it as an
unmodified file. The next update
will clue
CVS in to the fact that the file is unmodified,
and it will reset its stored timestamp so that the file
will not show up in future editor sessions.
If you want to avoid starting an editor you can specify the log message on the command line using the `-m' flag instead, like this:
$ cvs commit -m "Added an optimization pass" backend.c
Before you turn to other tasks you decide to remove your working copy of tc. One acceptable way to do that is of course
$ cd .. $ rm -r tc
but a better way is to use the release
command (see section release--Indicate that a Module is no longer in use):
$ cd .. $ cvs release -d tc M driver.c ? tc You have [1] altered files in this repository. Are you sure you want to release (and delete) directory `tc': n ** `release' aborted by user choice.
The release
command checks that all your modifications have been
committed. If history logging is enabled it also makes a note in the
history file. See section The history file.
When you use the `-d' flag with release
, it
also removes your working copy.
In the example above, the release
command wrote a couple of lines
of output. `? tc' means that the file `tc' is unknown to CVS.
That is nothing to worry about: `tc' is the executable compiler,
and it should not be stored in the repository. See section Ignoring files via cvsignore,
for information about how to make that warning go away.
See section release output, for a complete explanation of
all possible output from release
.
`M driver.c' is more serious. It means that the file `driver.c' has been modified since it was checked out.
The release
command always finishes by telling
you how many modified files you have in your working
copy of the sources, and then asks you for confirmation
before deleting any files or making any note in the
history file.
You decide to play it safe and answer n RET
when release
asks for confirmation.
You do not remember modifying `driver.c', so you want to see what has happened to that file.
$ cd tc $ cvs diff driver.c
This command runs diff
to compare the version of `driver.c'
that you checked out with your working copy. When you see the output
you remember that you added a command line option that enabled the
optimization pass. You check it in, and release the module.
$ cvs commit -m "Added an optimization pass" driver.c Checking in driver.c; /usr/local/cvsroot/tc/driver.c,v <-- driver.c new revision: 1.2; previous revision: 1.1 done $ cd .. $ cvs release -d tc ? tc You have [0] altered files in this repository. Are you sure you want to release (and delete) directory `tc': y
Go to the first, previous, next, last section, table of contents.