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.
CVS can access a repository by a variety of
means. It might be on the local computer, or it might
be on a computer across the room or across the world.
To distinguish various ways to access a repository, the
repository name can start with an access method.
For example, the access method
:local: means to
access a repository directory, so the repository
:local:/usr/local/cvsroot means that the
repository is in `/usr/local/cvsroot' on the
computer running CVS. For information on other
access methods, see section Remote repositories.
If the access method is omitted, then if the repository
does not contain `:', then
assumed. If it does contain `:' than either
:server: is assumed. For
example, if you have a local repository in
`/usr/local/cvsroot', you can use
/usr/local/cvsroot instead of
:local:/usr/local/cvsroot. But if (under
Windows NT, for example) your local repository is
`c:\src\cvsroot', then you must specify the access
method, as in
The repository is split in two parts. `$CVSROOT/CVSROOT' contains administrative files for CVS. The other directories contain the actual user-defined modules.
There are a couple of different ways to tell CVS
where to find the repository. You can name the
repository on the command line explicitly, with the
-d (for "directory") option:
cvs -d /usr/local/cvsroot checkout yoyodyne/tc
Or you can set the
variable to an absolute path to the root of the
repository, `/usr/local/cvsroot' in this example.
users should have this line in their `.cshrc' or
setenv CVSROOT /usr/local/cvsroot
bash users should instead have these lines in their
`.profile' or `.bashrc':
CVSROOT=/usr/local/cvsroot export CVSROOT
A repository specified with
$CVSROOT environment variable.
Once you've checked a working copy out from the
repository, it will remember where its repository is
(the information is recorded in the
`CVS/Root' file in the working copy).
-d option and the `CVS/Root' file both
$CVSROOT environment variable. If
-d option differs from `CVS/Root', the
former is used (and specifying
-d will cause
`CVS/Root' to be updated). Of course, for proper
operation they should be two ways of referring to the
For most purposes it isn't important how CVS stores information in the repository. In fact, the format has changed in the past, and is likely to change in the future. Since in almost all cases one accesses the repository via CVS commands; such changes need not be disruptive.
However, in some cases it may be necessary to understand how CVS stores data in the repository, for example you might need to track down CVS locks (see section Several developers simultaneously attempting to run CVS) or you might need to deal with the file permissions appropriate for the repository.
The overall structure of the repository is a directory tree corresponding to the directories in the working directory. For example, supposing the repository is in `/usr/local/cvsroot', here is a possible directory tree (showing only the directories):
/usr | +--local | | | +--cvsroot | | | | | +--CVSROOT | (administrative files) | +--gnu | | | +--diff | | (source code to GNU diff) | | | +--rcs | | (source code to RCS) | | | +--cvs | (source code to CVS) | +--yoyodyne | +--tc | | | +--man | | | +--testing | +--(other Yoyodyne software)
With the directories are history files for each file under version control. The name of the history file is the name of the corresponding file with `,v' appended to the end. Here is what the repository for the `yoyodyne/tc' directory might look like:
$CVSROOT| +--yoyodyne | | | +--tc | | | +--Makefile,v +--backend.c,v +--driver.c,v +--frontend.c,v +--parser.c,v +--man | | | +--tc.1,v | +--testing | +--testpgm.t,v +--test2.t,v
The history files contain, among other things, enough
information to recreate any revision of the file, a log
of all commit messages and the user-name of the person
who committed the revision. The history files are
known as RCS files, because the first program to
store files in that format was a version control system
known as RCS. For a full
description of the file format, see the
rcsfile(5), distributed with RCS. This
file format has become very common--many systems other
than CVS or RCS can at least import history
files in this format.
All `,v' files are created read-only, and you should not change the permission of those files. 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 UNIX group (see group(5)) 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.
This means that you can only control access to files on a per-directory basis.
Note that users must also have write access to check out files, because CVS needs to create lock files (see section Several developers simultaneously attempting to run CVS).
Also note that users must have write access to the `CVSROOT/val-tags' file. CVS uses it to keep track of what tags are valid tag names (it is sometimes updated when tags are used, as well as when they are created, though).
CVS tries to set up reasonable file permissions
for new directories that are added inside the tree, but
you must fix the permissions manually when a new
directory should have different permissions than its
parent directory. If you set the
environment variable that will control the file
permissions which CVS uses in creating directories
and/or files in the repository.
not affect the file permissions in the working
directory; such files have the permissions which are
typical for newly created files, except that sometimes
CVS creates them read-only (see the sections on
watches, section Telling CVS to watch certain files; -r, section Global options; or CVSREAD, section All environment variables which affect CVS).
Since CVS was not written to be run setuid, it is unsafe to try to run it setuid. You cannot use the setuid features of RCS together with CVS.
The directory `$CVSROOT/CVSROOT' contains some administrative files. See section Reference manual for the Administrative files, for a complete description. You can use CVS without any of these files, but some commands work better when at least the `modules' file is properly set up.
The most important of these files is the `modules' file. It defines all modules in the repository. This is a sample `modules' file.
CVSROOT CVSROOT modules CVSROOT modules cvs gnu/cvs rcs gnu/rcs diff gnu/diff tc yoyodyne/tc
The `modules' file is line oriented. In its
simplest form each line contains the name of the
module, whitespace, and the directory where the module
resides. The directory is a path relative to
$CVSROOT. The last four lines in the example
above are examples of such lines.
The line that defines the module called `modules' uses features that are not explained here. See section The modules file, for a full explanation of all the available features.
You edit the administrative files in the same way that you would edit any other module. Use `cvs checkout CVSROOT' to get a working copy, edit it, and commit your changes in the normal way.
It is possible to commit an erroneous administrative file. You can often fix the error and check in a new revision, but sometimes a particularly bad error in the administrative file makes it impossible to commit new revisions.
In some situations it is a good idea to have more than
one repository, for instance if you have two
development groups that work on separate projects
without sharing any code. All you have to do to have
several repositories is to specify the appropriate
repository, using the
variable, the `-d' option to CVS, or (once
you have checked out a working directory) by simply
allowing CVS to use the repository that was used
to check out the working directory
(see section Telling CVS where your repository is).
The big advantage of having multiple repositories is that they can reside on different servers. The big disadvantage is that you cannot have a single CVS command recurse into directories which comes from different repositories. Generally speaking, if you are thinking of setting up several repositories on the same machine, you might want to consider using several directories within the same repository.
None of the examples in this manual show multiple repositories.
To set up a CVS repository, choose a directory with ample disk space available for the revision history of the source files. It should be accessable (directly or via a networked file system) from all machines which want to use CVS in server or local mode; the client machines need not have any access to it other than via the CVS protocol. It is not possible to use CVS to read from a repository which one only has read access to; CVS needs to be able to create lock files (see section Several developers simultaneously attempting to run CVS).
To create a repository, run the
command. It will set up an empty repository in the
CVS root specified in the usual way
(see section The Repository). For example,
cvs -d /usr/local/cvsroot init
cvs init is careful to never overwrite any
existing files in the repository, so no harm is done if
cvs init on an already set-up
cvs init will enable history logging; if you
don't want that, remove the history file after running
cvs init. See section The history file.
Your working copy of the sources can be on a different machine than the repository. Generally, using a remote repository is just like using a local one, except that the format of the repository name is:
The details of exactly what needs to be set up depend on how you are connecting to the server.
If method is not specified, and the repository
name contains `:', then the default is
server, depending on your platform; both are
described in section Connecting with rsh.
CVS uses the `rsh' protocol to perform these operations, so the remote user host needs to have a `.rhosts' file which grants access to the local user.
For example, suppose you are the user `mozart' on the local machine `anklet.grunge.com', and the server machine is `chainsaw.brickyard.com'. On chainsaw, put the following line into the file `.rhosts' in `bach''s home directory:
Then test that
rsh is working with
rsh -l bach chainsaw.brickyard.com 'echo $PATH'
Next you have to make sure that
rsh will be able
to find the server. Make sure that the path which
rsh printed in the above example includes the
directory containing a program named
is the server. You need to set the path in
`.bashrc', `.cshrc', etc., not `.login'
or `.profile'. Alternately, you can set the
CVS_SERVER on the client
machine to the filename of the server you want to use,
for example `/usr/local/bin/cvs-1.6'.
There is no need to edit
inetd.conf or start a
CVS server daemon.
There are two access methods that you use in CVSROOT
:server: specifies an internal rsh
client, which is supported only by some CVS ports.
:ext: specifies an external rsh program. By
default this is
rsh but you may set the
CVS_RSH environment variable to invoke another
program which can access the remote server (for
remsh on HP-UX 9 because
something different). It must be a program which can
transmit data to and from the server without modifying
it; for example the Windows NT
rsh is not
suitable since it by default translates between CRLF
and LF. The OS/2 CVS port has a hack to pass `-b'
rsh to get around this, but since this could
potentially cause programs for programs other than the
rsh, it may change in the future. If
SSH or some other rsh
replacement, the instructions in the rest of this
section concerning `.rhosts' and so on are likely
to be incorrect; consult the documentation for your rsh
Continuing our example, supposing you want to access the module `foo' in the repository `/usr/local/cvsroot/', on machine `chainsaw.brickyard.com', you are ready to go:
cvs -d :ext:firstname.lastname@example.org:/usr/local/cvsroot checkout foo
(The `bach@' can be omitted if the username is the same on both the local and remote hosts.)
The CVS client can also connect to the server
using a password protocol. This is particularly useful
rsh is not feasible (for example,
the server is behind a firewall), and Kerberos also is
To use this method, it is necessary to make some adjustments on both the server and client sides.
On the server side, the file `/etc/inetd.conf'
needs to be edited so
inetd knows to run the
cvs pserver when it receives a
connection on the right port. By default, the port
number is 2401; it would be different if your client
were compiled with
CVS_AUTH_PORT defined to
something else, though.
inetd allows raw port numbers in
`/etc/inetd.conf', then the following (all on a
single line in `inetd.conf') should be sufficient:
2401 stream tcp nowait root /usr/local/bin/cvs cvs -b /usr/local/bin pserver
The `-b' option specifies the directory which contains the RCS binaries on the server. You could also use the `-T' option to specify a temporary directory.
inetd wants a symbolic service
name instead of a raw port number, then put this in
cvspserver instead of
2401 in `inetd.conf'.
Once the above is taken care of, restart your
inetd, or do whatever is necessary to force it
to reread its initialization files.
Because the client stores and transmits passwords in cleartext (almost--see section Security considerations with password authentication for details), a separate CVS password file may be used, so people don't compromise their regular passwords when they access the repository. This file is `$CVSROOT/CVSROOT/passwd' (see section The administrative files). Its format is similar to `/etc/passwd', except that it only has two fields, username and password. For example:
The password is encrypted according to the standard
crypt() function, so it is possible to
paste in passwords directly from regular Unix
When authenticating a password, the server first checks for the user in the CVS `passwd' file. If it finds the user, it compares against that password. If it does not find the user, or if the CVS `passwd' file does not exist, then the server tries to match the password using the system's user-lookup routine. When using the CVS `passwd' file, the server runs under as the username specified in the the third argument in the entry, or as the first argument if there is no third argument (in this way CVS allows imaginary usernames provided the CVS `passwd' file indicates corresponding valid system usernames). In any case, CVS will have no privileges which the (valid) user would not have.
Right now, the only way to put a password in the
CVS `passwd' file is to paste it there from
somewhere else. Someday, there may be a
Before connecting to the server, the client must log
in with the command
cvs login. Logging in
verifies a password with the server, and also records
the password for later transactions with the server.
cvs login command needs to know the
username, server hostname, and full repository path,
and it gets this information from the repository
argument or the
CVSROOT environment variable.
cvs login is interactive -- it prompts for a
cvs -d :pserver:email@example.com:/usr/local/cvsroot login CVS password:
The password is checked with the server; if it is
login succeeds, else it fails,
complaining that the password was incorrect.
Once you have logged in, you can force CVS to connect directly to the server and authenticate with the stored password:
cvs -d :pserver:firstname.lastname@example.org:/usr/local/cvsroot checkout foo
The `:pserver:' is necessary because without it,
CVS will assume it should use
connect with the server (see section Connecting with rsh).
(Once you have a working copy checked out and are
running CVS commands from within it, there is no
longer any need to specify the repository explicitly,
because CVS records it in the working copy's
Passwords are stored by default in the file `$HOME/.cvspass'. Its format is human-readable, but don't edit it unless you know what you are doing. The passwords are not stored in cleartext, but are trivially encoded to protect them from "innocent" compromise (i.e., inadvertently being seen by a system administrator who happens to look at that file).
CVS_PASSFILE environment variable overrides
this default. If you use this variable, make sure you
set it before
cvs login is run. If you
were to set it after running
cvs login, then
later CVS commands would be unable to look up the
password for transmission to the server.
CVS_PASSWORD environment variable overrides
all stored passwords. If it is set, CVS
will use it for all password-authenticated
The passwords are stored on the client side in a trivial encoding of the cleartext, and transmitted in the same encoding. The encoding is done only to prevent inadvertent password compromises (i.e., a system administrator accidentally looking at the file), and will not prevent even a naive attacker from gaining the password.
The separate CVS password file (see section Setting up the server for password authentication) allows people to use a different password for repository access than for login access. On the other hand, once a user has access to the repository, she can execute programs on the server system through a variety of means. Thus, repository access implies fairly broad system access as well. It might be possible to modify CVS to prevent that, but no one has done so as of this writing. Furthermore, there may be other ways in which having access to CVS allows people to gain more general access to the system; noone has done a careful audit.
In summary, anyone who gets the password gets repository access, and some measure of general system access as well. The password is available to anyone who can sniff network packets or read a protected (i.e., user read-only) file. If you want real security, get Kerberos.
The main disadvantage of using rsh is that all the data needs to pass through additional programs, so it may be slower. So if you have kerberos installed you can connect via a direct TCP connection, authenticating with kerberos.
To do this, CVS needs to be compiled with kerberos support; when configuring CVS it tries to detect whether kerberos is present or you can use the `--with-krb4' flag to configure.
The data transmitted is not encrypted by
default. Encryption support must be compiled into both
the client and server; use the
`--enable-encryption' configure option to turn it
on. You must then use the
-x global option to
You need to edit
inetd.conf on the server
machine to run
cvs kserver. The client uses
port 1999 by default; if you want to use another port
specify it in the
variable on the client.
When you want to use CVS, get a ticket in the
usual way (generally
kinit); it must be a ticket
which allows you to log into the server machine. Then
you are ready to go:
cvs -d :kserver:chainsaw.brickyard.com:/user/local/cvsroot checkout foo
Previous versions of CVS would fall back to a connection via rsh; this version will not do so.
Go to the first, previous, next, last section, table of contents.