The University of Queensland Homepage
School of ITEE ITEE Main Website

 CVS 0.9 manual

CVS--Concurrent Versions System

Version Management

with

CVS

release 0.9, for CVS 1.3+

Per Cederqvist

last updated 2 Nov 1993

Copyright (C) 1992, 1993 Signum Support AB

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the section entitled "GNU General Public License" is included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the section entitled "GNU General Public License" and this permission notice may be included in translations approved by the Free Software Foundation instead of in the original English.

About this manual

Up to this point, one of the weakest parts of CVS has been the documentation. CVS is a complex program. Previous versions of the manual were written in the manual page format, which is not really well suited for such a complex program.

When writing this manual, I had several goals in mind:

  • No knowledge of RCS should be necessary.
  • No previous knowledge of revision control software should be necessary. All terms, such as revision numbers, revision trees and merging are explained as they are introduced.
  • The manual should concentrate on the things CVS users want to do, instead of what the CVS commands can do. The first part of this manual leads you through things you might want to do while doing development, and introduces the relevant CVS commands as they are needed.
  • Information should be easy to find. In the reference manual in the appendices almost all information about every CVS command is gathered together. There is also an extensive index, and a lot of cross references.

This manual was contributed by Signum Support AB in Sweden. Signum is yet another in the growing list of companies that support free software. You are free to copy both this manual and the CVS program. See section GNU GENERAL PUBLIC LICENSE, for the details. Signum Support offers support contracts and binary distribution for many programs, such as CVS, GNU Emacs, the GNU C compiler and others. You can also buy hardcopies of this manual from us. Write to us for more information.

Signum Support AB
Box 2044
S-580 02  Linkoping
Sweden

Email: info@signum.se
Phone: +46 (0)13 - 21 46 00
Fax:   +46 (0)13 - 21 47 00

Checklist for the impatient reader

CVS is a complex system. You will need to read the manual to be able to use all of its capabilities. There are dangers that can easily be avoided if you know about them, and this manual tries to warn you about them. This checklist is intended to help you avoid the dangers without reading the entire manual. If you intend to read the entire manual you can skip this table.

Binary files
CVS can handle binary files, but you must have RCS release 5.5 or later and a release of GNU diff that supports the `-a' flag (release 1.15 and later are OK). You must also configure both RCS and CVS to handle binary files when you install them. Keword substitution can be a source of trouble with binary files. See section Keyword substitution, for solutions.
The admin command
Uncareful use of the admin command can cause CVS to cease working. See section admin--Administration front end for rcs, before trying to use it.

Credits

Roland Pesch, Cygnus Support <pesch@cygnus.com> wrote the manual pages which were distributed with CVS 1.3. Appendix A and B contain much text that was extracted from them. He also read an early draft of this manual and contributed many ideas and corrections.

The mailing-list info-cvs is sometimes informative. I have included information from postings made by the following persons: David G. Grubbs <dgg@think.com>.

Some text has been extracted from the man pages for RCS.

The CVS FAQ (see section What is CVS?) by David G. Grubbs has been used as a check-list to make sure that this manual is as complete as possible. (This manual does however not include all of the material in the FAQ). The FAQ contains a lot of useful information.

In addition, the following persons have helped by telling me about mistakes I've made: Roxanne Brunskill <rbrunski@datap.ca>, Kathy Dyer <dyer@phoenix.ocf.llnl.gov>, Karl Pingle <pingle@acuson.com>, Thomas A Peterson <tap@src.honeywell.com>, Inge Wallin <ingwa@signum.se>, Dirk Koschuetzki <koschuet@fmi.uni-passau.de> and Michael Brown <brown@wi.extrel.com>.

BUGS

This manual is still very new. Here is a list of known deficiencies in it:

  • In the examples, the output from CVS is sometimes displayed, sometimes not.
  • The input that you are supposed to type in the examples should have a different font than the output from the computer.
  • This manual should be clearer about what file permissions you should set up in the repository, and about setuid/setgid.
  • Some of the chapters are not yet complete. They are noted by comments in the `cvs.texinfo' file.
  • This list is not complete. If you notice any error, omission, or something that is unclear, please send mail to ceder@signum.se.

I hope that you will find this manual useful, despite the above-mentioned shortcomings.


Linkoping, October 1993
Per Cederqvist

What is CVS?

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 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 via anonymous ftp from a number of sites, for instance prep.ai.mit.edu in `pub/gnu'.

There is a mailing list for CVS where bug reports can be sent, questions can be asked, an FAQ is posted, and discussion about future enhancements to CVS take place. To submit a message to the list, write to <info-cvs@prep.ai.mit.edu>. To subscribe or unsubscribe, write to <info-cvs-request@prep.ai.mit.edu>. Please be specific about your email address.

Work is in progress on creating a newsgroup for CVS-related topics. It will appear somewhere under the `gnu.' hierarchy. Gateways to and from the mailing list will be set up.

The FTP site think.com has some CVS material in the `/pub/cvs' subdirectory. Currently (late summer 1993) it contains an excellent FAQ (Frequently Asked Questions, with answers), and an improved (but unofficial) version of CVS.

CVS is not...

CVS can do a lot of things for you, but it does not try to be everything for everyone.

CVS is not a build system.
Though the structure of your repository and modules file interact with your build system (e.g. `Makefile's), they are essentially independent. CVS does not dictate how you build anything. It merely stores files for retrieval in a tree structure you devise. CVS does not dictate how to use disk space in the checked out working directories. If you write your `Makefile's or scripts in every directory so they have to know the relative positions of everything else, you wind up requiring the entire repository to be checked out. That's simply bad planning. If you modularize your work, and construct a build system that will share files (via links, mounts, 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. You must use your brain and a collection of other tools to provide a build scheme to match your plans. Of course, you should place the tools created to support such a build system (scripts, `Makefile's, etc) under CVS.
CVS is not a substitute for management.
Your managers and project leaders are expected to talk to you frequently enough to make certain you are aware of schedules, merge points, branch names and release dates. If they don't, CVS can't help. CVS is an instrument for making sources dance to your tune. But you are the piper and the composer. No instrument plays itself or writes its own music.
CVS is not a substitute for developer communication.
When faced with conflicts within a single file, most developers manage to resolve them without too much effort. But a more general definition of "conflict" includes problems too difficult to solve without communication between developers. CVS cannot determine when simultaneous changes within a single file, or across a whole collection of files, will logically conflict with one another. Its concept of a conflict is purely textual, arising when two changes to the same base file are near enough to spook the merge (i.e. 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 is not a configuration management system.
CVS is a source control system. The phrase "configuration management" is a marketing term, not an industry-recognized set of functions. A true "configuration management system" would contain elements of the following:
  • Source control.
  • Dependency tracking.
  • Build systems (i.e. What to build and how to find things during a build. What is shared? What is local?)
  • Bug tracking.
  • Automated Testing procedures.
  • Release Engineering documentation and procedures.
  • Tape Construction.
  • Customer Installation.
  • A way for users to run different versions of the same software on the same host at the same time.

CVS provides only the first.

This section is taken from release 2.3 of the CVS FAQ.

Basic concepts

CVS stores all files in a centralized repository: a directory (such as `/usr/local/cvsroot') which is populated with a hierarchy of files and directories.

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.

The files in the repository are organized in modules. Each module is made up of one or more files, and can include files from several directories. A typical usage is to define one module per project.

Revision numbers

Each version of a file has a unique revision number. Revision numbers look like `1.1', `1.2', `1.3.2.2' or even `1.3.2.2.4.5'. A revision number always has an even number of period-separated decimal integers. By default revision 1.1 is the first revision of a file. Each successive revision is given a new number by increasing the rightmost number by one. The following figure displays a few revisions, with newer revisions to the right.

       +-----+    +-----+    +-----+    +-----+    +-----+
       ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !
       +-----+    +-----+    +-----+    +-----+    +-----+

CVS is not limited to linear development. The revision tree can be split into branches, where each branch is a self-maintained line of development. Changes made on one branch can easily be moved back to the main trunk.

Each branch has a branch number, consisting of an odd number of period-separated decimal integers. The branch number is created by appending an integer to the revision number where the corresponding branch forked off. Having branch numbers allows more than one branch to be forked off from a certain revision.

All revisions on a branch have revision numbers formed by appending an ordinal number to the branch number. The following figure illustrates branching with an example.

                                                     +-------------+
                          Branch 1.2.2.3.2 ->        ! 1.2.2.3.2.1 !
                                                   / +-------------+
                                                  /
                                                 /
                 +---------+    +---------+    +---------+    +---------+
Branch 1.2.2 -> _! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 !----! 1.2.2.4 !
               / +---------+    +---------+    +---------+    +---------+
              /
             /
+-----+    +-----+    +-----+    +-----+    +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !      <- The main trunk
+-----+    +-----+    +-----+    +-----+    +-----+
                !
                !
                !   +---------+    +---------+    +---------+
Branch 1.2.4 -> +---! 1.2.4.1 !----! 1.2.4.2 !----! 1.2.4.3 !
                    +---------+    +---------+    +---------+

The exact details of how the branch number is constructed is not something you normally need to be concerned about, but here is how it works: When CVS creates a branch number it picks the first unused even integer, starting with 2. So when you want to create a branch from revision 6.4 it will be numbered 6.4.2. All branch numbers ending in a zero (such as 6.4.0) are used internally by CVS (see section Magic branch numbers). The branch 1.1.1 has a special meaning. See section Tracking third-party sources.

Versions, revisions and releases

A file can have several versions, as described above. Likewise, a software product can have several versions. A software product is often given a version number such as `4.1.1'.

Versions in the first sense are called revisions in this document, and versions in the second sense are called releases. To avoid confusion, the word version is almost never used in this document.

A sample session

This section describes a typical work-session using CVS. It assumes that a repository is set up (see section The Repository).

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'.

Getting the source

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 tc
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.

Committing your changes

When you have checked that the compiler is still compilable you decide to make a new version of `backend.c'.

$ 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 $EDITOR determines which editor is started. If $EDITOR is not set, 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 an optimization pass" backend.c

Cleaning up

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) module `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.

Viewing differences

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) module `tc': y

The Repository

Figure 3 below shows a typical setup of a repository. Only directories are shown below.

/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)

The $CVSROOT environment variable should always be set to an absolute path to the root of the repository, `/usr/local/cvsroot' in this example. With this setup all csh and tcsh users should have this line in their `.cshrc' or `.tcshrc' files:

setenv CVSROOT /usr/local/cvsroot

sh and bash users should instead have these lines in their `.profile' or `.bashrc':

CVSROOT=/usr/local/cvsroot
export CVSROOT

There is nothing magical about the name `/usr/local/cvsroot'. You can choose to place the repository anywhere you like, but $CVSROOT must always point to it.

The repository is split in two parts. `$CVSROOT/CVSROOT' contains administrative files for CVS. The other directories contain the actual user-defined modules.

User modules

  $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 figure above shows the contents of the `tc' module inside the repository. As you can see all file names end in `,v'. The files are history files. They 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. CVS uses the facilities of RCS, a simpler version control system, to maintain these files. For a full description of the file format, see the man page rcsfile(5).

File permissions

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.

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.

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 administrative files

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         -i mkmodules CVSROOT
modules         -i mkmodules 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 for lines in the example above are examples of such lines.

Each module definition can contain options. The `-i mkmodules' is an example of an option. It arranges for CVS to run the mkmodules program whenever any file in the module CVSROOT is committed. That program is responsible for checking out read-only copies from the RCS history files of all the administrative files. These read-only copies are used internally by CVS. You should never edit them directly.

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.

Editing administrative files

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.

Multiple repositories

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 set $CVSROOT to the repository you want to use at the moment.

There are disadvantages to having more than one repository. In CVS 1.3 you must make sure that $CVSROOT always points to the correct repository. If the same filename is used in two repositories, and you mix up the setting of $CVSROOT, you might lose data. CVS 1.4 solves this problem by saving the repository information in the local `CVS' administration files. If you try to use the wrong repository, CVS will warn you of the attempt and then exit.

Notwithstanding, it can be confusing to have two or more repositories.

All examples in this manual assume that you have a single repository.

Creating a repository

See the instructions in the `INSTALL' file in the CVS distribution.

Starting a project with CVS

Since CVS 1.x is bad at renaming files and moving them between directories, the first thing you do when you start a new project should be to think through your file organization. It is not impossible--just awkward--to rename or move files in CVS 1.x. See section Moving and renaming files.

What to do next depends on the situation at hand.

Setting up the files

The first step is to create the files inside the repository. This can be done in a couple of different ways.

Creating a module from a number 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 `dir', and you want them to appear in the repository as `$CVSROOT/yoyodyne/dir', you can do this:

$ cd dir
$ cvs import -m "Imported sources" yoyodyne/dir yoyo start

Unless you supply a log message with the `-m' flag, CVS starts an editor and prompts for a message. The string `yoyo' 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. See section Tracking third-party sources, for more information about them.

You can now verify that it worked, and remove your original source directory.

$ cd ..
$ mv dir dir.orig
$ cvs checkout yoyodyne/dir       # Explanation below
$ ls -R yoyodyne
$ rm -r dir.orig

Erasing the original sources is a good idea, to make sure that you do not accidentally edit them in dir, bypassing CVS. Of course, it would be wise to make sure that you have a backup of the sources before you remove them.

The checkout command can either take a module name as argument (as it has done in all previous examples) or a path name relative to $CVSROOT, as it did in the example above.

It is a good idea to check that the permissions CVS sets on the directories inside `$CVSROOT' are reasonable, and that they belong to the proper groups. See section File permissions.

Creating a module from scratch

For a new project, the easiest thing to do is probably to create an empty directory structure, like this:

$ mkdir tc
$ mkdir tc/man
$ mkdir tc/testing

After that, you use the import command to create the corresponding (empty) directory structure inside the repository:

$ cd tc
$ cvs import -m "Created directory structure" yoyodyne/dir yoyo start

Then, use add to add files (and new directories) as they appear.

Check that the permissions CVS sets on the directories inside `$CVSROOT' are reasonable.

Defining the module

The next step is to define the module in the `modules' file. Some CVS commands work without this step, but others (most notably release) require that all modules are properly defined in the `modules' file.

In simple cases these steps are sufficient to define a module.

  1. Get a working copy of the modules file.
$ cvs checkout modules
$ cd modules
  1. Edit the file and insert a line that defines the module. See section The administrative files, for an introduction. See section The modules file, for a full description of the modules file. You can use the following line to define the module `tc':
tc   yoyodyne/tc
  1. Commit your changes to the modules file.
$ cvs commit -m "Added the tc module." modules
  1. Release the modules module.
$ cd ..
$ cvs release -d modules

Multiple developers

When more than one person works on a software project things often get complicated. Often, two people try to edit the same file simultaneously. Some other version control systems (including RCS and SCCS) try to solve that particular problem by introducing file locking, so that only one person can edit each file at a time. Unfortunately, file locking can be very counter-productive. If two persons want to edit different parts of a file, there may be no reason to prevent either of them from doing so.

CVS does not use file locking. Instead, it allows many people to edit their own working copy of a file simultaneously. The first person that commits his changes has no automatic way of knowing that another has started to edit it. Others will get an error message when they try to commit the file. They must then use CVS commands to bring their working copy up to date with the repository revision. This process is almost automatic, and explained in this chapter.

There are many ways to organize a team of developers. CVS does not try to enforce a certain organization. It is a tool that can be used in several ways. It is often useful to inform the group of commits you have done. CVS has several ways of automating that process. See section Informing others about commits. See section Revision management, for more tips on how to use CVS.

File status

After you have checked out a file out from CVS, it is in one of these four states:

Up-to-date
The file is identical with the latest revision in the repository.
Locally modified
You have edited the file, and not yet committed your changes.
Needing update
Someone else has committed a newer revision to the repository.
Needing merge
Someone else have committed a newer revision to the repository, and you have also made modifications to the file.

You can use the status command to find out the status of a given file. See section status--Status info on the revisions.

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, an overlap occurs. In such cases a warning is printed, and the resulting file includes both versions of the lines that overlap, delimited by special markers. See section update--Bring work tree in sync with repository, for a complete description of the update command.

Conflicts example

Suppose revision 1.4 of `driver.c' contains this:

#include <stdio.h>

void main()
{
    parse();
    if (nerr == 0)
        gencode();
    else
        fprintf(stderr, "No code generated.\n");
    exit(nerr == 0 ? 0 : 1);
}

Revision 1.6 of `driver.c' contains this:

#include <stdio.h>

int main(int argc,
         char **argv)
{
    parse();
    if (argc != 1)
    {
        fprintf(stderr, "tc: No args expected.\n");
        exit(1);
    }
    if (nerr == 0)
        gencode();
    else
        fprintf(stderr, "No code generated.\n");
    exit(!!nerr);
}

Your working copy of `driver.c', based on revision 1.4, contains this before you run `cvs update':

#include <stdlib.h>
#include <stdio.h>

void main()
{
    init_scanner();
    parse();
    if (nerr == 0)
        gencode();
    else
        fprintf(stderr, "No code generated.\n");
    exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}

You run `cvs update':

$ cvs update driver.c
RCS file: /usr/local/cvsroot/yoyodyne/tc/driver.c,v
retrieving revision 1.4
retrieving revision 1.6
Merging differences between 1.4 and 1.6 into driver.c
rcsmerge warning: overlaps during merge
cvs update: conflicts found in driver.c
C driver.c

CVS tells you that there were some conflicts. Your original working file is saved unmodified in `.#driver.c.1.4'. The new version of `driver.c' contains this:

#include <stdlib.h>
#include <stdio.h>

int main(int argc,
         char **argv)
{
    init_scanner();
    parse();
    if (argc != 1)
    {
        fprintf(stderr, "tc: No args expected.\n");
        exit(1);
    }
    if (nerr == 0)
        gencode();
    else
        fprintf(stderr, "No code generated.\n");
<<<<<<< driver.c
    exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
=======
    exit(!!nerr);
>>>>>>> 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 <stdlib.h>
#include <stdio.h>

int main(int argc,
         char **argv)
{
    init_scanner();
    parse();
    if (argc != 1)
    {
        fprintf(stderr, "tc: No args expected.\n");
        exit(1);
    }
    if (nerr == 0)
        gencode();
    else
        fprintf(stderr, "No code generated.\n");
    exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}

You can now go ahead and commit this as revision 1.7.

$ cvs commit -m "Initialize scanner. Use symbolic exit values." driver.c
Checking in driver.c;
/usr/local/cvsroot/yoyodyne/tc/driver.c,v  <--  driver.c
new revision: 1.7; previous revision: 1.6
done

If you use release 1.04 or later of pcl-cvs (a GNU Emacs front-end for CVS) you can use an Emacs package called emerge to help you resolve conflicts. See the documentation for pcl-cvs.

Informing others about commits

It is often useful to inform others when you commit a new revision of a file. The `-i' option of the `modules' file, or the `loginfo' file, can be used to automate this process. See section The modules file. See section Loginfo. You can use these features of CVS to, for instance, instruct CVS to mail a message to all developers, or post a message to a local newsgroup.

Branches

So far, all revisions shown in this manual have been on the main trunk of the revision tree, i.e., all revision numbers have been of the form x.y. One useful feature, especially when maintaining several releases of a software product at once, is the ability to make branches on the revision tree. Tags, symbolic names for revisions, will also be introduced in this chapter.

Tags--Symbolic revisions

The revision numbers live a life of their own. They need not have anything at all to do with the release numbers of your software product. Depending on how you use CVS the revision numbers might change several times between two releases. As an example, some of the source files that make up RCS 5.6 have the following revision numbers:

ci.c            5.21
co.c            5.9
ident.c         5.3
rcs.c           5.12
rcsbase.h       5.11
rcsdiff.c       5.10
rcsedit.c       5.11
rcsfcmp.c       5.9
rcsgen.c        5.10
rcslex.c        5.11
rcsmap.c        5.2
rcsutil.c       5.10

You can use the tag command to give a symbolic name to a certain revision of a file. You can use the `-v' flag to the status command to see all tags that a file has, and which revision numbers they represent. (The output of status unfortunately uses the word "version" instead of "revision".)

The following example shows how you can add a tag to a file. The commands must be issued inside your working copy of the module. That is, you should issue the command in the directory where `backend.c' resides.

$ cvs tag release-0-4 backend.c
T backend.c
$ cvs status -v backend.c
===================================================================
File: backend.c         Status: Up-to-date

    Version:            1.4     Tue Dec  1 14:39:01 1992
    RCS Version:        1.4     /usr/local/cvsroot/yoyodyne/tc/backend.c,v
    Sticky Tag:         (none)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        release-0-4                     (revision: 1.4)

There is seldom reason to tag a file in isolation. A more common use is to tag all the files that constitute a module with the same tag at strategic points in the development life-cycle, such as when a release is made.

$ cvs tag release-1-0 .
cvs tag: Tagging .
T Makefile
T backend.c
T driver.c
T frontend.c
T parser.c

(When you give CVS a directory as argument, it generally applies the operation to all the files in that directory, and (recursively), to any subdirectories that it may contain. See section Recursive behavior.)

The checkout command has a flag, `-r', that lets you check out a certain revision of a module. This flag makes it easy to retrieve the sources that make up release 1.0 of the module `tc' at any time in the future:

$ cvs checkout -r release-1-0 tc

This is useful, for instance, if someone claims that there is a bug in that release, but you cannot find the bug in the current working copy.

You can also check out a module as it was at any given date. See section checkout options.

When you tag more than one file with the same tag you can think about the tag as "a curve drawn through a matrix of filename vs. revision number." Say we have 5 files with the following revisions:

        file1   file2   file3   file4   file5

        1.1     1.1     1.1     1.1  /--1.1*      <-*-  TAG
        1.2*-   1.2     1.2    -1.2*-
        1.3  \- 1.3*-   1.3   / 1.3
        1.4          \  1.4  /  1.4
                      \-1.5*-   1.5
                        1.6

At some time in the past, the * versions were tagged. You can think of the tag as a handle attached to the curve drawn through the tagged revisions. When you pull on the handle, you get all the tagged revisions. Another way to look at it is that you "sight" through a set of revisions that is "flat" along the tagged revisions, like this:

        file1   file2   file3   file4   file5

                        1.1
                        1.2
                1.1     1.3                       _
        1.1     1.2     1.4     1.1              /
        1.2*----1.3*----1.5*----1.2*----1.1     (--- <--- Look here
        1.3             1.6     1.3              \_
        1.4                     1.4
                                1.5

What branches are good for

Suppose that release 1.0 of tc has been made. You are continuing to develop tc, planning to create release 1.1 in a couple of months. After a while your customers start to complain about a fatal bug. You check out release 1.0 (see section Tags--Symbolic revisions) and find the bug (which turns out to have a trivial fix). However, the current revision of the sources are in a state of flux and are not expected to be stable for at least another month. There is no way to make a bugfix release based on the newest sources.

The thing to do in a situation like this is to create a branch on the revision trees for all the files that make up release 1.0 of tc. You can then make modifications to the branch without disturbing the main trunk. When the modifications are finished you can select to either incorporate them on the main trunk, or leave them on the branch.

Creating a branch

The rtag command can be used to create a branch. The rtag command is much like tag, but it does not require that you have a working copy of the module. See section rtag--Add a tag to the RCS file. (You can also use the tag command; see section tag--Add a symbolic tag to checked out version of RCS file).

$ cvs rtag -b -r release-1-0 release-1-0-patches tc

The `-b' flag makes rtag create a branch (rather than just a symbolic revision name). `-r release-1-0' says that this branch should be rooted at the node (in the revision tree) that corresponds to the tag `release-1-0'. Note that the numeric revision number that matches `release-1-0' will probably be different from file to file. The name of the new branch is `release-1-0-patches', and the module affected is `tc'.

To fix the problem in release 1.0, you need a working copy of the branch you just created.

$ cvs checkout -r release-1-0-patches tc
$ cvs status -v driver.c backend.c
===================================================================
File: driver.c          Status: Up-to-date

    Version:            1.7     Sat Dec  5 18:25:54 1992
    RCS Version:        1.7     /usr/local/cvsroot/yoyodyne/tc/driver.c,v
    Sticky Tag:         release-1-0-patches (branch: 1.7.2)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        release-1-0-patches             (branch: 1.7.2)
        release-1-0                     (revision: 1.7)

===================================================================
File: backend.c         Status: Up-to-date

    Version:            1.4     Tue Dec  1 14:39:01 1992
    RCS Version:        1.4     /usr/local/cvsroot/yoyodyne/tc/backend.c,v
    Sticky Tag:         release-1-0-patches (branch: 1.4.2)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        release-1-0-patches             (branch: 1.4.2)
        release-1-0                     (revision: 1.4)
        release-0-4                     (revision: 1.4)

As the output from the status command shows the branch number is created by adding a digit at the tail of the revision number it is based on. (If `release-1-0' corresponds to revision 1.4, the branch's revision number will be 1.4.2. For obscure reasons CVS always gives branches even numbers, starting at 2. See section Revision numbers).

Sticky tags

The `-r release-1-0-patches' flag that was given to checkout is sticky, that is, it will apply to subsequent commands in this directory. If you commit any modifications, they are committed on the branch. You can later merge the modifications into the main trunk. See section Merging.

$ vi driver.c   # Fix the bugs
$ cvs commit -m "Fixed initialization bug" driver.c
Checking in driver.c;
/usr/local/cvsroot/yoyodyne/tc/driver.c,v  <--  driver.c
new revision: 1.7.2.1; previous revision: 1.7
done
$ cvs status -v driver.c
===================================================================
File: driver.c          Status: Up-to-date

    Version:            1.7.2.1 Sat Dec  5 19:35:03 1992
    RCS Version:        1.7.2.1 /usr/local/cvsroot/yoyodyne/tc/driver.c,v
    Sticky Tag:         release-1-0-patches (branch: 1.7.2)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        release-1-0-patches             (branch: 1.7.2)
        release-1-0                     (revision: 1.7)

The sticky tags will remain on your working files until you delete them with `cvs update -A'. See section update--Bring work tree in sync with repository.

Sticky tags are not just for branches. If you check out a certain revision (such as 1.4) it will also become sticky. Subsequent `cvs update' will not retrieve the latest revision until you reset the tag with `cvs update -A'.

See the descriptions in Appendix A for more information about sticky tags. Dates and some other options can also be sticky. Again, see Appendix A for details.

Merging

You can include the changes made between any two revisions into your working copy, by merging. You can then commit that revision, and thus effectively copy the changes onto another branch.

Merging an entire branch

You can merge changes made on a branch into your working copy by giving the `-j branch' flag to the update command. With one `-j branch' option it merges the changes made between the point where the branch forked and newest revision on that branch (into your working copy).

The `-j' stands for "join". In previous versions of CVS there was a special command, `cvs join', that was used to merge changes between branches.

Consider this revision tree:

+-----+    +-----+    +-----+    +-----+    +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !      <- The main trunk
+-----+    +-----+    +-----+    +-----+    +-----+
                !
                !
                !   +---------+    +---------+    +---------+
Branch R1fix -> +---! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 !
                    +---------+    +---------+    +---------+

The branch 1.2.2 has been given the tag (symbolic name) `R1fix'. The following example assumes that the module `mod' contains only one file, `m.c'.

$ cvs checkout mod               # Retrieve the latest revision, 1.5

$ cvs update -j R1fix m.c        # Merge all changes made on the branch,
                                 # i.e. the changes between revision 1.2
                                 # and 1.2.2.3, into your working copy
                                 # of the file.

$ cvs commit -m "Included R1fix" # Create revision 1.6.

A conflict can result from a merge operation. If that happens, you should resolve it before committing the new revision. See section Conflicts example.

The checkout command also supports the `-j branch' flag. The same effect as above could be achieved with this:

$ cvs checkout -j R1fix mod
$ cvs commit -m "Included R1fix"

Merging differences between any two revisions

With two `-j revision' flags, the update (and checkout) command can merge the differences between any two revisions into your working file.

$ cvs update -j 1.5 -j 1.3 backend.c

will remove all changes made between revision 1.3 and 1.5. Note the order of the revisions!

If you try to use this option with the checkout command, remember that the numeric revisions will probably be very different between the various files that make up a module. You almost always use symbolic tags rather than revision numbers with the checkout command.

Recursive behavior

Almost all of the subcommands of CVS work recursively when you specify a directory as an argument. For instance, consider this directory structure:

      $HOME
        |
        +--tc
        |   |
            +--CVS
            |      (internal CVS files)
            +--Makefile
            +--backend.c
            +--driver.c
            +--frontend.c
            +--parser.c
            +--man
            |    |
            |    +--CVS
            |    |  (internal CVS files)
            |    +--tc.1
            |     
            +--testing
                 |
                 +--CVS
                 |  (internal CVS files)
                 +--testpgm.t
                 +--test2.t

If `tc' is the current working directory, the following is true:

  • `cvs update testing' is equivalent to `cvs update testing/testpgm.t testing/test2.t'
  • `cvs update testing man' updates all files in the subdirectories
  • `cvs update .' or just `cvs update' updates all files in the tc module

If no arguments are given to update it will update all files in the current working directory and all its subdirectories. In other words, `.' is a default argument to update. This is also true for most of the CVS subcommands, not only the update command.

The recursive behavior of the CVS subcommands can be turned off with the `-l' option.

$ cvs update -l         # Don't update files in subdirectories

Adding files to a module

To add a new file to a module, follow these steps.

  • You must have a working copy of the module. See section Getting the source.
  • Create the new file inside your working copy of the module.
  • Use `cvs add filename' to tell CVS that you want to version control the file.
  • Use `cvs commit filename' to actually check in the file into the repository. Other developers cannot see the file until you perform this step.
  • If the file contains binary data it might be necessary to change the default keyword substitution. See section Keyword substitution. See section admin examples.

You can also use the add command to add a new directory inside a module.

Unlike most other commands, the add command is not recursive. You cannot even type `cvs add foo/bar'! Instead, you have to

$ cd foo
$ cvs add bar

See section add--Add a new file/directory to the repository, for a more complete description of the add command.

Removing files from a module

Modules change. New files are added, and old files disappear. Still, you want to be able to retrieve an exact copy of old releases of the module.

Here is what you can do to remove a file from a module, but remain able to retrieve old revisions:

  • Make sure that you have not made any uncommitted modifications to the file. See section Viewing differences, for one way to do that. You can also use the status or update command. If you remove the file without committing your changes, you will of course not be able to retrieve the file as it was immediately before you deleted it.
  • Remove the file from your working copy of the module. You can for instance use rm.
  • Use `cvs remove filename' to tell CVS that you really want to delete the file.
  • Use `cvs commit filename' to actually perform the removal of the file from the repository.

What happens when you commit the removal of the file is that inside the source repository, it is moved into a subdirectory called `Attic'. CVS normally doesn't look in that directory when you run e.g. checkout. However, if you are retrieving a certain revision via e.g. `cvs checkout -r some-tag', it will look at the files inside the `Attic' and include any files that contain the specified tag.

This method is simple and works quite well, but it has some known deficiencies:

  • If you remove the file `foo.c', you cannot later create a new file called `foo.c' unless you manually remove the file `Attic/foo.c,v' inside the repository. On the other hand, if you remove `Attic/foo.c,v' you will of course not be able to retrieve any revision of the old file `foo.c'.
  • If the file `bar.c' is present in release 1.0 of a product, and was accidentally removed in release 1.1, you cannot easily resurrect it to release 1.2. You have to move the file out of the `Attic' manually inside the repository. (Do a `mv Attic/file file').

There is a design for a rename database that will solve these problems and many others, but it is not yet implemented.

Tracking third-party sources

If you modify a program to better fit your site, you probably want to include your modifications when the next release of the program arrives. CVS can help you with this task.

In the terminology used in CVS, the supplier of the program is called a vendor. The unmodified distribution from the vendor is checked in on its own branch, the vendor branch. CVS reserves branch 1.1.1 for this use.

When you modify the source and commit it, your revision will end up on the main trunk. When a new release is made by the vendor, you commit it on the vendor branch and copy the modifications onto the main trunk.

Use the import command to create and update the vendor branch. After a successful import the vendor branch is made the `head' revision, so anyone that checks out a copy of the file gets that revision. When a local modification is committed it is placed on the main trunk, and made the `head' revision.

Importing a module for the first time

Use the import command to check in the sources for the first time. When you use the import command to track third-party sources, the vendor tag and release tags are useful. The vendor tag is a symbolic name for the branch (which is always 1.1.1, unless you use the `-b branch' flag---See section import options). The release tags are symbolic names for a particular release, such as `FSF_0_04'.

Suppose you use wdiff (a variant of diff that ignores changes that only involve whitespace), and are going to make private modifications that you want to be able to use even when new releases are made in the future. You start by importing the source to your repository:

$ tar xfz wdiff-0.04.tar.gz
$ cd wdiff-0.04
$ cvs import -m "Import of FSF v. 0.04" fsf/wdiff FSF WDIFF_0_04

The vendor tag is named `FSF' in the above example, and the only release tag assigned is `WDIFF_0_04'.

Updating a module with the import command

When a new release of the source arrives, you import it into the repository with the same import command that you used to set up the repository in the first place. The only difference is that you specify a different release tag this time.

$ tar xfz wdiff-0.05.tar.gz
$ cd wdiff-0.05
$ cvs import -m "Import of FSF v. 0.05" fsf/wdiff FSF WDIFF_0_05

For files that have not been modified locally, the newly created revision becomes the head revision. If you have made local changes, import will warn you that you must merge the changes into the main trunk, and tell you to use `checkout -j' to do so.

$ cvs checkout -jFSF:yesterday -jFSF wdiff

The above command will check out the latest revision of `wdiff', merging the changes made on the vendor branch `FSF' since yesterday into the working copy. If any conflicts arise during the merge they should be resolved in the normal way (see section Conflicts example). Then, the modified files may be committed.

CVS assumes that you do not import more than one release of a product per day. If you do, you can always use something like this instead:

$ cvs checkout -jWDIFF_0_04 -jWDIFF_0_05 wdiff

In this case, the two above commands are equivalent.

Moving and renaming files

One of the biggest design flaws with the current release of CVS is that it is very difficult to move a file to a different directory or rename it. There are workarounds, and they all have their strong and weak points. (Moving or renaming a directory is even harder. See section Moving and renaming directories).

The examples below assume that the file old is renamed to new. Both files reside in the same module, module, but not necessarily in the same directory. The relative path to the module inside the repository is assumed to be module.

Moving outside the repository

One way to move the file is to copy old to new, and then issue the normal CVS commands to remove old from the repository, and add new to it. (Both old and new could contain relative paths inside the module).

$ mv old new
$ cvs remove old
$ cvs add new 
$ cvs commit -m "Renamed old to new" old new

Advantages:

  • Checking out old revisions works correctly.

Disadvantages:

  • You cannot easily see the history of the file across the rename.
  • Unless you use the `-r rev' (see section commit options) flag when new is committed its revision numbers will start at 1.0 again.

Moving the history file

This method is more dangerous, since it involves moving files inside the repository. Read this entire section before trying it out!

$ cd $CVSROOT/module
$ mv old,v new,v

Advantages:

  • The log of changes is maintained intact.
  • The revision numbers are not affected.

Disadvantages:

  • Old releases of the module cannot easily be fetched from the repository. (The file will show up as new even in revisions from the time before it was renamed).
  • There is no log information of when the file was renamed.
  • Nasty things might happen if someone accesses the history file while you are moving it. Make sure no one else runs any of the CVS commands while you move it.

Copying the history file

This is probably the best way to do the renaming. It is safe, but not without drawbacks.

# Copy the RCS file inside the repository
$ cd $CVSROOT/module
$ cp old,v new,v
# Remove the old file
$ cd ~/module
$ rm old
$ cvs remove old
$ cvs commit old
# Remove all tags from new
$ cvs update new
$ cvs log new             # Remember the tag names
$ cvs tag -d tag1
$ cvs tag -d tag2
...

By removing the tags you will be able to check out old revisions of the module.

Advantages:

  • Checking out old revisions works correctly, as long as you use `-rtag' and not `-Ddate' to retrieve the revisions.
  • The log of changes is maintained intact.
  • The revision numbers are not affected.

Disadvantages:

  • You cannot easily see the history of the file across the rename.
  • Unless you use the `-r rev' (see section commit options) flag when new is committed its revision numbers will start at 1.0 again.

Moving and renaming directories

If you want to be able to retrieve old versions of the module, you must move each file in the directory with the CVS commands. See section Moving outside the repository. The old, empty directory will remain inside the repository, but it will not appear in your workspace when you check out the module in the future.

If you really want to rename or delete a directory, you can do it like this:

  1. Inform everyone who has a copy of the module that the directory will be renamed. They should commit all their changes, and remove their working copies of the module, before you take the steps below.
  2. Rename the directory inside the repository.
$ cd $CVSROOT/module
$ mv old-dir new-dir
  1. Fix the CVS administrative files, if necessary (for instance if you renamed an entire module).
  2. Tell everyone that they can check out the module and continue working.

If someone had a working copy of the module the CVS commands will cease to work for him, until he removes the directory that disappeared inside the repository.

It is almost always better to move the files in the directory instead of moving the directory. If you move the directory you are unlikely to be able to retrieve old releases correctly, since they probably depend on the name of the directories.

Keyword substitution

As long as you edit source files inside your working copy of a module you can always find out the state of your files via `cvs status' and `cvs log'. But as soon as you export the files from your development environment it becomes harder to identify which revisions they are.

RCS uses a mechanism known as keyword substitution (or keyword expansion) to help identifying the files. Embedded strings of the form $keyword$ and $keyword:...$ in a file are replaced with strings of the form $keyword:value$ whenever you obtain a new revision of the file.

RCS Keywords

This is a list of the keywords that RCS currently (in release 5.6.0.1) supports:

$Author$
The login name of the user who checked in the revision.
$Date$
The date and time (UTC) the revision was checked in.
$Header$
A standard header containing the full pathname of the RCS file, the revision number, the date (UTC), the author, the state, and the locker (if locked). Files will normally never be locked when you use CVS.
$Id$
Same as $Header$, except that the RCS filename is without a path.
$Locker$
The login name of the user who locked the revision (empty if not locked, and thus almost always useless when you are using CVS).
$Log$
The log message supplied during commit, preceded by a header containing the RCS filename, the revision number, the author, and the date (UTC). Existing log messages are not replaced. Instead, the new log message is inserted after $Log:...$. Each new line is prefixed with a comment leader which RCS guesses from the file name extension. It can be changed with cvs admin -c. See section admin options. This keyword is useful for accumulating a complete change log in a source file, but for several reasons it can be problematic. See section Problems with the $Log$ keyword..
$RCSfile$
The name of the RCS file without a path.
$Revision$
The revision number assigned to the revision.
$Source$
The full pathname of the RCS file.
$State$
The state assigned to the revision. States can be assigned with cvs admin -s---See section admin options.

Using keywords

To include a keyword string you simply include the relevant text string, such as $Id$, inside the file, and commit the file. CVS will automatically expand the string as part of the commit operation.

It is common to embed $Id$ string in the C source code. This example shows the first few lines of a typical file, after keyword substitution has been performed:

static char *rcsid="$Id: samp.c,v 1.5 1993/10/19 14:57:32 ceder Exp $";
/* The following lines will prevent gcc version 2.x
   from issuing an "unused variable" warning. */
#if __GNUC__ == 2
#define USE(var) static void * use_##var = (&use_##var, (void *) &var) 
USE (rcsid);
#endif

Even though a clever optimizing compiler could remove the unused variable rcsid, most compilers tend to include the string in the binary. Some compilers have a #pragma directive to include literal text in the binary.

The ident command (which is part of the RCS package) can be used to extract keywords and their values from a file. This can be handy for text files, but it is even more useful for extracting keywords from binary files.

$ ident samp.c
samp.c:
     $Id: samp.c,v 1.5 1993/10/19 14:57:32 ceder Exp $
$ gcc samp.c
$ ident a.out
a.out:
     $Id: samp.c,v 1.5 1993/10/19 14:57:32 ceder Exp $

SCCS is another popular revision control system. It has a command, what, which is very similar to ident and used for the same purpose. Many sites without RCS have SCCS. Since what looks for the character sequence @(#) it is easy to include keywords that are detected by either command. Simply prefix the RCS keyword with the magic SCCS phrase, like this:

static char *id="@(#) $Id: ab.c,v 1.5 1993/10/19 14:57:32 ceder Exp $";

Avoiding substitution

Keyword substitution has its disadvantages. Sometimes you might want the literal text string `$'Author$ to appear inside a file without RCS interpreting it as a keyword and expanding it into something like `$'Author: ceder $.

There is unfortunately no way to selectively turn off keyword substitution. You can use `-ko' (see section Substitution modes) to turn off keyword substitution entirely. (If you put binaries under version control you are strongly encouraged to use that option, for obvious reasons).

In many cases you can avoid using RCS keywords in the source, even though they appear in the final product. For example, the source for this manual contains `$@asis{}Author$' whenever the text `$'Author$ should appear. In nroff and troff you can embed the null-character \& inside the keyword for a similar effect.

Substitution modes

You can control how RCS expands keywords through the use of the `-k' option (see section Common command options). The `-k' option is available with the add, checkout, diff and update commands.

Five different modes are available. They are:

`-kkv'
Generate keyword strings using the default form, e.g. $Revision: 5.7 $ for the Revision keyword.
`-kkvl'
Like `-kkv', except that a locker's name is always inserted if the given revision is currently locked. This option is normally not useful when CVS is used.
`-kk'
Generate only keyword names in keyword strings; omit their values. For example, for the Revision keyword, generate the string $Revision$ instead of $Revision: 5.7 $. This option is useful to ignore differences due to keyword substitution when comparing different revisions of a file.
`-ko'
Generate the old keyword string, present in the working file just before it was checked in. For example, for the Revision keyword, generate the string $Revision: 1.1 $ instead of $Revision: 5.7 $ if that is how the string appeared when the file was checked in. This can be useful for binary file formats that cannot tolerate any changes to substrings that happen to take the form of keyword strings.
`-kv'
Generate only keyword values for keyword strings. For example, for the Revision keyword, generate the string 5.7 instead of $Revision: 5.7 $. This can help generate files in programming languages where it is hard to strip keyword delimiters like $Revision: $ from a string. However, further keyword substitution cannot be performed once the keyword names are removed, so this option should be used with care. This option is always use by cvs export---see section export--Export sources from CVS, similar to checkout.

Problems with the $Log$ keyword.

The $Log$ keyword is somewhat controversial. As long as you are working on your development system the information is easily accessible even if you do not use the $Log$ keyword--just do a cvs log. Once you export the file the history information might be useless anyhow.

A more serious concern is that RCS is not good at handling $Log$ entries when a branch is merged onto the main trunk. Conflicts often result from the merging operation.

People also tend to "fix" the log entries in the file (correcting spelling mistakes and maybe even factual errors). If that is done the information from cvs log will not be consistent with the information inside the file. This may or may not be a problem in real life.

It has been suggested that the $Log$ keyword should be inserted last in the file, and not in the files header, if it is to be used at all. That way the long list of change messages will not interfere with everyday source file browsing.

Revision management

If you have read this far, you probably have a pretty good grasp on what CVS can do for you. This chapter talks a little about things that you still have to decide.

If you are doing development on your own using CVS you could probably skip this chapter. The questions this chapter takes up become more important when more than one person is working in a repository.

When to commit?

Your group should decide which policy to use regarding commits. Several policies are possible, and as your experience with CVS grows you will probably find out what works for you.

If you commit files too quickly you might commit files that do not even compile. If your partner updates his working sources to include your buggy file, he will be unable to compile the code. On the other hand, other persons will not be able to benefit from the improvements you make to the code if you commit very seldom, and conflicts will probably be more common.

It is common to only commit files after making sure that they can be compiled. Some sites require that the files pass a test suite. Policies like this can be enforced using the commitinfo file (see section Commitinfo), but you should think twice before you enforce such a convention. By making the development environment too controlled it might become too regimented and thus counter-productive to the real goal, which is to get software written.

Reference manual for CVS commands

This appendix describes every subcommand of CVS in detail. It also describes how to invoke CVS.

Overall structure of CVS commands

The first release of CVS consisted of a number of shell-scripts. Today CVS is implemented as a single program that is a front-end to RCS and diff. The overall format of all CVS commands is:

cvs [ cvs_options ] cvs_command [ command_options ] [ command_args ]
cvs
The program that is a front-end to RCS.
cvs_options
Some options that affect all sub-commands of CVS. These are described below.
cvs_command
One of several different sub-commands. Some of the commands have aliases that can be used instead; those aliases are noted in the reference manual for that command. There are only two situations where you may omit `cvs_command': `cvs -H' elicits a list of available commands, and `cvs -v' displays version information on CVS itself.
command_options
Options that are specific for the command.
command_args
Arguments to the commands.

There is unfortunately some confusion between cvs_options and command_options. For example, `-q' can often (but not always) be given as both a cvs_option and a command_option. `-l', when given as a cvs_option, only affects some of the commands. When it is given as a command_option is has a different meaning, and is accepted by more commands. In other words, do not take the above categorization too seriously. Look at the documentation instead.

Default options and the ~/.cvsrc file

There are some command_options that are used so often that you might have set up an alias or some other means to make sure you always specify that option. One example (1) is that many people find the default output of the `diff' command to be very hard to read, and that either context diffs or unidiffs are much easier to understand.

The `~/.cvsrc' file is a way that you can add default options to cvs_commands within cvs, instead of relying on aliases or other shell scripts.

The format of the `~/.cvsrc' file is simple. The file is searched for a line that begins with the same name as the cvs_command being executed. If a match is found, then the remainder of the line is split up (at whitespace characters) into separate options and added to the command arguments before any options from the command line.

If a command has two names (e.g., checkout and co), only the name used on the command line will be used to match against the file. So if this is the contents of the user's `~/.cvsrc' file:

log -N
diff -u
update -P
co -P

the command `cvs checkout foo' would not have the `-P' option added to the arguments, while `cvs co foo' would.

With the example file above, the output from `cvs diff foobar' will be in unidiff format. `cvs diff -c foobar' will provide context diffs, as usual. Since diff doesn't have an option to specify use of the "old" format, you would need to use the `-f' option to `cvs' to turn off use of the `~/.cvsrc' options.

Global options

The available `cvs_options' (that are given to the left of `cvs_command') are:

-b bindir
Use bindir as the directory where RCS programs are located. Overrides the setting of the $RCSBIN environment variable and any precompiled directory. This parameter should be specified as an absolute pathname.
-d cvs_root_directory
Use cvs_root_directory as the root directory pathname of the repository. Overrides the setting of the $CVSROOT environment variable. This parameter should be specified as an absolute pathname.
-e editor
Use editor to enter revision log information. Overrides the setting of the $EDITOR environment variable.
-f
Do not read the `~/.cvsrc' file. This option is most often used because of the non-orthogonality of the CVS option set. For example, the `cvs log' option `-N' (turn off display of tag names) does not have a corresponding option to turn the display on. So if you have `-N' in the `~/.cvsrc' entry for `diff', you may need to use `-f' to show the tag names. (2)
-H
Display usage information about the specified `cvs_command' (but do not actually execute the command). If you don't specify a command name, `cvs -H' displays a summary of all the commands available.
-l
Do not log the cvs_command in the command history (but execute it anyway). See section history--Show status of files and users, for information on command history.
-n
Do not change any files. Attempt to execute the `cvs_command', but only to issue reports; do not remove, update, or merge any existing files, or create any new files.
-Q
Cause the command to be really quiet; the command will only generate output for serious problems.
-q
Cause the command to be somewhat quiet; informational messages, such as reports of recursion through subdirectories, are suppressed.
-r
Make new working files files read-only. Same effect as if the $CVSREAD environment variable is set (see section All environment variables which affect CVS). The default is to make working files writable.
-t
Trace program execution; display messages showing the steps of CVS activity. Particularly useful with `-n' to explore the potential impact of an unfamiliar command.
-v
Display version and copyright information for CVS.
-w
Make new working files read-write. Overrides the setting of the $CVSREAD environment variable. Files are created read-write by default, unless $CVSREAD is set or `-r' is given.

Common command options

This section describes the `command_options' that are available across several CVS commands. These options are always given to the right of `cvs_command'. Not all commands support all of these options; each option is only supported for commands where it makes sense. However, when a command has one of these options you can almost always count on the same behavior of the option as in other commands. (Other command options, which are listed with the individual commands, may have different behavior from one CVS command to the other).

Warning: the `history' command is an exception; it supports many options that conflict even with these standard options.

-D date_spec
Use the most recent revision no later than date_spec. date_spec is a single argument, a date description specifying a date in the past. The specification is sticky when you use it to make a private copy of a source file; that is, when you get a working file using `-D', CVS records the date you specified, so that further updates in the same directory will use the same date (unless you explicitly override it; see section update--Bring work tree in sync with repository). A wide variety of date formats are supported by the underlying RCS facilities, similar to those described in co(1), but not exactly the same. The date_spec is interpreted as being in the local timezone, unless a specific timezone is specified. Examples of valid date specifications include:
                    1 month ago
                    2 hours ago
                    400000 seconds ago
                    last year
                    last Monday
                    yesterday
                    a fortnight ago
                    3/31/92 10:00:07 PST
                    January 23, 1987 10:05pm
                    22:00 GMT

`-D' is available with the checkout, diff, export, history, rdiff, rtag, and update commands. (The history command uses this option in a slightly different way; see section history options). Remember to quote the argument to the `-D' flag so that your shell doesn't interpret spaces as argument separators. A command using the `-D' flag can look like this:

$ cvs diff -D "1 hour ago" cvs.texinfo

-f
When you specify a particular date or tag to CVS commands, they normally ignore files that do not contain the tag (or did not exist prior to the date) that you specified. Use the `-f' option if you want files retrieved even when there is no match for the tag or date. (The most recent revision of the file will be used). `-f' is available with these commands: checkout, export, rdiff, rtag, and update. Warning: The commit command also has a `-f' option, but it has a different behavior for that command. See section commit options.
-H
Help; describe the options available for this command. This is the only option supported for all CVS commands.
-k kflag
Alter the default RCS processing of keywords. See section Keyword substitution, for the meaning of kflag. Your kflag specification is sticky when you use it to create a private copy of a source file; that is, when you use this option with the checkout or update commands, CVS associates your selected kflag with the file, and continues to use it with future update commands on the same file until you specify otherwise. The `-k' option is available with the add, checkout, diff and update commands.
-l
Local; run only in current working directory, rather than recursing through subdirectories. Warning: this is not the same as the overall `cvs -l' option, which you can specify to the left of a cvs command! Available with the following commands: checkout, commit, diff, export, log, remove, rdiff, rtag, status, tag, and update.
-m message
Use message as log information, instead of invoking an editor. Available with the following commands: add, commit and import.
-n
Do not run any checkout/commit/tag program. (A program can be specified to run on each of these activities, in the modules database (see section The modules file); this option bypasses it). Warning: this is not the same as the overall `cvs -n' option, which you can specify to the left of a cvs command! Available with the checkout, commit, export, and rtag commands.
-P
Prune (remove) directories that are empty after being updated, on checkout, or update. Normally, an empty directory (one that is void of revision-controlled files) is left alone. Specifying `-P' will cause these directories to be silently removed from your checked-out sources. This does not remove the directory from the repository, only from your checked out copy. Note that this option is implied by the `-r' or `-D' options of checkout and export.
-p
Pipe the files retrieved from the repository to standard output, rather than writing them in the current directory. Available with the checkout and update commands.
-Q
Cause the command to be really quiet; the command will only generate output for serious problems. Available with the following commands: checkout, import, export, rdiff, rtag, tag, and update.
-q
Cause the command to be somewhat quiet; informational messages, such as reports of recursion through subdirectories, are suppressed. Available with the following commands: checkout, import, export, rtag, tag, and update.
-r tag
Use the revision specified by the tag argument instead of the default head revision. As well as arbitrary tags defined with the tag or rtag command, two special tags are always available: `HEAD' refers to the most recent version available in the repository, and `BASE' refers to the revision you last checked out into the current working directory. The tag specification is sticky when you use this option with checkout or update to make your own copy of a file: CVS remembers the tag and continues to use it on future update commands, until you specify otherwise. The tag can be either a symbolic or numeric tag. See section Tags--Symbolic revisions. Specifying the `-q' option along with the `-r' option is often useful, to suppress the warning messages when the RCS history file does not contain the specified tag. Warning: this is not the same as the overall `cvs -r' option, which you can specify to the left of a cvs command! `-r' is available with the checkout, commit, diff, history, export, rdiff, rtag, and update commands.

add--Add a new file/directory to the repository

  • Synopsis: add [-k kflag] [-m 'message'] files...
  • Requires: repository, working directory.
  • Changes: working directory.
  • Synonym: new

Use the add command to create a new file or directory in the source repository. The files or directories specified with add must already exist in the current directory (which must have been created with the checkout command). To add a whole new directory hierarchy to the source repository (for example, files received from a third-party vendor), use the import command instead. See section import--Import sources into CVS, using vendor branches.

If the argument to add refers to an immediate sub-directory, the directory is created at the correct place in the source repository, and the necessary CVS administration files are created in your working directory. If the directory already exists in the source repository, add still creates the administration files in your version of the directory. This allows you to use add to add a particular directory to your private sources even if someone else created that directory after your checkout of the sources. You can do the following:

$ mkdir new_directory
$ cvs add new_directory
$ cvs update new_directory

An alternate approach using update might be:

$ cvs update -d new_directory

(To add any available new directories to your working directory, it's probably simpler to use checkout (see section checkout--Check out sources for editing) or `update -d' (see section update--Bring work tree in sync with repository)).

The added files are not placed in the source repository until you use commit to make the change permanent. Doing an add on a file that was removed with the remove command will resurrect the file, unless a commit command intervened. See section remove examples for an example.

Unlike most other commands add never recurses down directories. It cannot yet handle relative paths. Instead of

$ cvs add foo/bar.c

you have to do

$ cd foo
$ cvs add bar.c

add options

There are only two options you can give to `add':

-k kflag
This option specifies the default way that this file will be checked out. See rcs(1) and co(1). The kflag argument (see section Substitution modes) is stored in the RCS file and can be changed with admin -k (see section admin options). Specifying `-ko' is useful for checking in binaries that should not have the RCS id strings expanded. Warning: this option is reported to be broken in version 1.3 and 1.3-s2 of CVS. Use `admin -k' after the commit instead. See section admin examples.
-m description
Using this option, you can give a description for the file. This description appears in the history log (if it is enabled, see section The history file). It will also be saved in the RCS history file inside the repository when the file is committed. The log command displays this description. The description can be changed using `admin -t'. See section admin--Administration front end for rcs. If you omit the `-m description' flag, an empty string will be used. You will not be prompted for a description.

add examples

To add the file `backend.c' to the repository, with a description, the following can be used.

$ cvs add -m "Optimizer and code generation passes." backend.c
$ cvs commit -m "Early version. Not yet compilable." backend.c

admin--Administration front end for rcs

  • Requires: repository, working directory.
  • Changes: repository.
  • Synonym: rcs

This is the CVS interface to assorted administrative RCS facilities, documented in rcs(1). admin simply passes all its options and arguments to the rcs command; it does no filtering or other processing. This command does work recursively, however, so extreme care should be used.

admin options

Not all valid rcs options are useful together with CVS. Some even makes it impossible to use CVS until you undo the effect!

This description of the available options is based on the `rcs(1)' man page, but modified to suit readers that are more interrested in CVS than RCS.

-Aoldfile
Might not work together with CVS. Append the access list of oldfile to the access list of the RCS file.
-alogins
Might not work together with CVS. Append the login names appearing in the comma-separated list logins to the access list of the RCS file.
-b[rev]
Breaks CVS. When used with bare RCS, this option sets the default branch to rev. If rev is omitted, the default branch is reset to the (dynamically) highest branch on the trunk. Use sticky tags instead, as in cvs co -r. See section Sticky tags.
-cstring
Useful with CVS. Sets the comment leader to string. The comment leader is printed before every log message line generated by the keyword $Log$ (see section Keyword substitution). This is useful for programming languages without multi-line comments. RCS initially guesses the value of the comment leader from the file name extension when the file is first committed.
-e[logins]
Might not work together with CVS. Erase the login names appearing in the comma-separated list logins from the access list of the RCS file. If logins is omitted, erase the entire access list.
-I
Run interactively, even if the standard input is not a terminal.
-i
Useless with CVS. When using bare RCS, this is used to create and initialize a new RCS file, without depositing a revision.
-ksubst
Useful with CVS. Set the default keyword substitution to subst. See section Keyword substitution. Giving an explicit `-k' option to cvs update or cvs checkout overrides this default. cvs export always uses -kv, regardless of which keyword substitution is set with cvs admin.
-l[rev]
Probably useless with CVS. With bare RCS, this option can be used to lock the revision with number rev. If a branch is given, lock the latest revision on that branch. If rev is omitted, lock the latest revision on the default branch.
-L
Probably useless with CVS. Used with bare RCS to set locking to strict. Strict locking means that the owner of an RCS file is not exempt from locking for checkin.
-mrev:msg
Replace the log message of revision rev with msg.
-Nname[:[rev]]
Act like `-n', except override any previous assignment of name.
-nname[:[rev]]
Associate the symbolic name name with the branch or revision rev. It is normally better to use `cvs tag' or `cvs rtag' instead. Delete the symbolic name if both `:' and rev are omitted; otherwise, print an error message if name is already associated with another number. If rev is symbolic, it is expanded before association. A rev consisting of a branch number followed by a `.' stands for the current latest revision in the branch. A `:' with an empty rev stands for the current latest revision on the default branch, normally the trunk. For example, `rcs -nname: RCS/*' associates name with the current latest revision of all the named RCS files; this contrasts with `rcs -nname:$ RCS/*' which associates name with the revision numbers extracted from keyword strings in the corresponding working files.
-orange
Useful, but dangerous, with CVS (see below). Deletes (outdates) the revisions given by range. A range consisting of a single revision number means that revision. A range consisting of a branch number means the latest revision on that branch. A range of the form `rev1:rev2' means revisions rev1 to rev2 on the same branch, `:rev' means from the beginning of the branch containing rev up to and including rev, and `rev:' means from revision rev to the end of the branch containing rev. None of the outdated revisions may have branches or locks. Due to the way CVS handles branches rev cannot be specified symbolically if it is a branch. See section Magic branch numbers, for an explanation. Make sure that no-one has checked out a copy of the revision you outdate. Strange things will happen if he starts to edit it and tries to check it back in. For this reason, you should never use this option to take back a bogus commit unless you work alone. Instead, you should fix the file and commit a new revision.
-q
Run quietly; do not print diagnostics.
-sstate[:rev]
Useful with CVS. Set the state attribute of the revision rev to state. If rev is a branch number, assume the latest revision on that branch. If rev is omitted, assume the latest revision on the default branch. Any identifier is acceptable for state. A useful set of states is `Exp' (for experimental), `Stab' (for stable), and `Rel' (for released). By default, the state of a new revision is set to `Exp' when it is created. The state is visible in the output from cvs log (see section log--Print out 'rlog' information for files), and in the `$'Log$ and `$'State$ keywords (see section Keyword substitution).
-t[file]
Useful with CVS. Write descriptive text from the contents of the named file into the RCS file, deleting the existing text. The file pathname may not begin with `-'. If file is omitted, obtain the text from standard input, terminated by end-of-file or by a line containing `.' by itself. Prompt for the text if interaction is possible; see `-I'. The descriptive text can be seen in the output from `cvs log' (see section log--Print out 'rlog' information for files).
-t-string
Similar to `-tfile'. Write descriptive text from the string into the RCS file, deleting the existing text.
-U
Probably useless with CVS. Used with bare RCS to set locking to non-strict. Non-strict locking means that the owner of a file need not lock a revision for checkin.
-u[rev]
Probably useless with CVS. With bare RCS, unlock the revision with number rev. If a branch is given, unlock the latest revision on that branch. If rev is omitted, remove the latest lock held by the caller. Normally, only the locker of a revision may unlock it. Somebody else unlocking a revision breaks the lock. This causes a mail message to be sent to the original locker. The message contains a commentary solicited from the breaker. The commentary is terminated by end-of-file or by a line containing . by itself.
-Vn
Emulate RCS version n. Use -Vn to make an RCS file acceptable to RCS version n by discarding information that would confuse version n.
-xsuffixes
Useless with CVS. Use suffixes to characterize RCS files.

admin examples

Outdating is dangerous

First, an example of how not to use the admin command. It is included to stress the fact that this command can be quite dangerous unless you know exactly what you are doing.

The `-o' option can be used to outdate old revisions from the history file. If you are short on disc this option might help you. But think twice before using it--there is no way short of restoring the latest backup to undo this command!

The next line is an example of a command that you would not like to execute.

$ cvs admin -o:R_1_02 .

The above command will delete all revisions up to, and including, the revision that corresponds to the tag R_1_02. But beware! If there are files that have not changed between R_1_02 and R_1_03 the file will have the same numerical revision number assigned to the tags R_1_02 and R_1_03. So not only will it be impossible to retrieve R_1_02; R_1_03 will also have to be restored from the tapes!

Handling binary files

If you use CVS to store binary files, where keyword strings (see section Keyword substitution) might accidentally appear inside the file, you should use cvs admin -ko to make sure that they are not modified automatically. Here is an example of how you can create a new file using the `-ko' flag:

$ echo '$Id$' > kotest
$ cvs add -m"A test file" kotest
$ cvs ci -m"First checkin; contains a keyword" kotest
$ cvs admin -ko kotest
$ rm kotest
$ cvs update kotest

When you check in the file `kotest' the keywords are expanded. (Try the above example, and do a cat kotest after every command!) The cvs admin -ko command sets the default keyword substitution method for this file, but it does not alter the working copy of the file that you have. The easiest way to get the unexpanded version of `kotest' is to remove it and check it out again.

Comment leaders

If you use the $Log$ keyword and you do not agree with the guess for comment leader that CVS has done, you can enforce your will with cvs admin -c. This might be suitable for nroff source:

$ cvs admin -c'.\" ' *.man
$ rm *.man
$ cvs update

The two last steps are to make sure that you get the versions with correct comment leaders in your working files.

checkout--Check out sources for editing

  • Synopsis: checkout [options] modules...
  • Requires: repository.
  • Changes: working directory.
  • Synonyms: co, get

Make a working directory containing copies of the source files specified by modules. You must execute checkout before using most of the other CVS commands, since most of them operate on your working directory.

The modules part of the command are either symbolic names for some collection of source directories and files, or paths to directories or files in the repository. The symbolic names are defined in the `modules' file. See section The modules file.

Depending on the modules you specify, checkout may recursively create directories and populate them with the appropriate source files. You can then edit these source files at any time (regardless of whether other software developers are editing their own copies of the sources); update them to include new changes applied by others to the source repository; or commit your work as a permanent change to the source repository.

Note that checkout is used to create directories. The top-level directory created is always added to the directory where checkout is invoked, and usually has the same name as the specified module. In the case of a module alias, the created sub-directory may have a different name, but you can be sure that it will be a sub-directory, and that checkout will show the relative path leading to each file as it is extracted into your private work area (unless you specify the `-Q' option).

Running checkout on a directory that was already built by a prior checkout is also permitted, and has the same effect as specifying the `-d' option to the update command, that is, any new directories that have been created in the repository will appear in your work area. See section update--Bring work tree in sync with repository.

checkout options

These standard options are supported by checkout (see section Common command options, for a complete description of them):

-D date
Use the most recent revision no later than date. This option is sticky, and implies `-P'.
-f
Only useful with the `-D date' or `-r tag' flags. If no matching revision is found, retrieve the most recent revision (instead of ignoring the file).
-k kflag
Process RCS keywords according to kflag. See co(1). This option is sticky; future updates of this file in this working directory will use the same kflag. The status command can be viewed to see the sticky options. See section status--Status info on the revisions.
-l
Local; run only in current working directory.
-n
Do not run any checkout program (as specified with the `-o' option in the modules file; see section The modules file).
-P
Prune empty directories.
-p
Pipe files to the standard output.
-Q
Really quiet.
-q
Somewhat quiet.
-r tag
Use revision tag. This option is sticky, and implies `-P'.

In addition to those, you can use these special command options with checkout:

-A
Reset any sticky tags, dates, or `-k' options. (If you get a working file using one of the `-r', `-D', or `-k' options, CVS remembers the corresponding tag, date, or kflag and continues using it for future updates; use the `-A' option to make CVS forget these specifications, and retrieve the `head' revision of the file).
-c
Copy the module file, sorted, to the standard output, instead of creating or modifying any files or directories in your working directory.
-d dir
Create a directory called dir for the working files, instead of using the module name. Unless you also use `-N', the paths created under dir will be as short as possible.
-j tag
Merge the changes made between the resulting revision and the revision that it is based on (e.g., if tag refers to a branch, CVS will merge all changes made on that branch into your working file). With two `-j tag' options, CVS will merge in the changes between the two respective revisions. This can be used to undo changes made between two revisions (see section Merging differences between any two revisions) in your working copy, or to move changes between different branches. In addition, each -j option can contain an optional date specification which, when used with branches, can limit the chosen revision to one within a specific date. An optional date is specified by adding a colon (:) to the tag. An example might be what import tells you to do when you have just imported sources that have conflicts with local changes:
$ cvs checkout -jTAG:yesterday -jTAG module
-N
Only useful together with `-d dir'. With this option, CVS will not shorten module paths in your working directory. (Normally, CVS shortens paths as much as possible when you specify an explicit target directory).
-s
Like `-c', but include the status of all modules, and sort it by the status string. See section The modules file, for info about the `-s' option that is used inside the modules file to set the module status.

checkout examples

Get a copy of the module `tc':

$ cvs checkout tc

Get a copy of the module `tc' as it looked one day ago:

$ cvs checkout -D yesterday tc

commit--Check files into the repository

  • Version 1.3 Synopsis: commit [-lnR] [-m 'log_message' | -f file] [-r revision] [files...]
  • Version 1.3.1 Synopsis: commit [-lnRf] [-m 'log_message' | -F file] [-r revision] [files...]
  • Requires: working directory, repository.
  • Changes: repository.
  • Synonym: ci

Warning: The `-f file' option will probably be renamed to `-F file', and `-f' will be given a new behavior in future releases of CVS.

Use commit when you want to incorporate changes from your working source files into the source repository.

If you don't specify particular files to commit, all of the files in your working current directory are examined. commit is careful to change in the repository only those files that you have really changed. By default (or if you explicitly specify the `-R' option), files in subdirectories are also examined and committed if they have changed; you can use the `-l' option to limit commit to the current directory only.

commit verifies that the selected files are up to date with the current revisions in the source repository; it will notify you, and exit without committing, if any of the specified files must be made current first with update (see section update--Bring work tree in sync with repository). commit does not call the update command for you, but rather leaves that for you to do when the time is right.

When all is well, an editor is invoked to allow you to enter a log message that will be written to one or more logging programs (see section The modules file, and see section Loginfo) and placed in the RCS history file inside the repository. This log message can be retrieved with the log command; See section log--Print out 'rlog' information for files. You can specify the log message on the command line with the `-m message' option, and thus avoid the editor invocation, or use the `-f file' option to specify that the argument file contains the log message.

commit options

These standard options are supported by commit (see section Common command options, for a complete description of them):

-l
Local; run only in current working directory.
-n
Do not run any module program.
-R
Commit directories recursively. This is on by default.
-r <