This is ossdev.info, produced by makeinfo version 4.3 from
../book/ossdev/main.texi.

START-INFO-DIR-ENTRY
* CVS Book: (cvsbook).          A CVS tutorial and reference.
END-INFO-DIR-ENTRY

Copyright (C) 1999, 2000 Karl Fogel <kfogel@red-bean.com>

This document is free software; you can redistribute and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

This document is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

This manual describes how to use and administer CVS (Concurrent Versions
System).  It is part of a larger work entitled `Open Source Development
With CVS'; please see the introduction for details.

This is version 1.21 of this manual.


File: ossdev.info,  Node: Top,  Next: Introduction,  Up: (dir)



Top
***

* Menu:

* Introduction::               What is this book?
* An Overview of CVS::         Basic CVS usage -- a tutorial.
* Repository Administration::  How to run a CVS repository.
* Advanced CVS::               What the gurus know.
* Tips And Troubleshooting::   FAQs and real-life experiences.
* CVS Reference::              A reference to CVS commands, variables, etc.
* Third-Party Tools::          Other tools that work with CVS.
* Index::
* GNU General Public License::
* GNU Free Documentation License::


File: ossdev.info,  Node: Introduction,  Next: An Overview of CVS,  Prev: Top,  Up: Top

Introduction
************

This is a set of free, online chapters about using CVS (Concurrent
Versions System) for collaboration and version control.  It covers
everything from CVS installation and basic concepts all the way to
advanced usage and administration.  It is intended for anyone who uses
or plans to use CVS.

These chapters are excerpted from a larger work called `Open Source
Development With CVS' (published by The Coriolis Group
(http://www.coriolis.com/), ISBN 1-57610-490-7).  The remainder of that
book - chapters 1, 3, 5, and 7 - deals with the challenges and
philosophical issues of running an Open Source project using CVS.

While the free chapters here constitute a complete CVS book by
themselves, we certainly hope you'll like them enough to purchase a
treeware copy of the entire book!  You can order it directly from the
publisher, at
`http://www.coriolis.com/bookstore/bookdetail.cfm?id=1576104907'.

These chapters are released under the GNU General Public License
(http://www.gnu.org/copyleft/gpl.html).  For more information about
free software in general, visit `http://www.gnu.org/', and particularly
`http://www.gnu.org/philosophy/free-sw.html'.

To submit comments or errata regarding any of this material, please send
email to <bug-cvsbook@red-bean.com>.  For news and updates, visit
`http://cvsbook.red-bean.com/'.


File: ossdev.info,  Node: An Overview of CVS,  Next: Repository Administration,  Prev: Introduction,  Up: Top

An Overview of CVS
******************

     _I can't imagine programming without it... that would be like
     parachuting without a parachute!_

                        _-Brian Fitzpatrick on CVS_

This chapter introduces the fundamentals of CVS, and then provides an
in-depth guided tour of everyday CVS usage.  Concepts are presented
sequentially, so if you're new to CVS, the best way to read this is to
start at the beginning and go straight through, without skipping
anything.

* Menu:

* Basic Concepts::              How to think like CVS.
* A Day With CVS::              Guided tour through a sample CVS session.
* Other Useful CVS Commands::   Random useful things.
* Branches::                    Splitting development into parallel streams.


File: ossdev.info,  Node: Basic Concepts,  Next: A Day With CVS,  Up: An Overview of CVS

Basic Concepts
==============

If you've never used CVS (or any version control system) before, it's
easy to get tripped up by some of its underlying assumptions.  What
seems to cause the most initial confusion about CVS is that it is used
for two apparently unrelated purposes: record keeping and collaboration.
It turns out, however, that these two functions are closely connected.

Record keeping became necessary because people wanted to compare a
program's current state with how it was at some point in the past.  For
example, in the normal course of implementing a new feature, a developer
may bring the program into a thoroughly broken state, where it will
probably remain until the feature is mostly finished.  Unfortunately,
this is just the time when someone usually calls to report a bug in the
last publicly released version.  To debug the problem (which may also
exist in the current version of the sources), the program has to be
brought back to a useable state.

Restoring the state poses no difficulty if the source code history is
kept under CVS.  The developer can simply say, in effect, "Give me the
program as it was three weeks ago", or perhaps "Give me the program as
it was at the time of our last public release".  If you've never had
this kind of convenient access to historical snapshots before, you may
be surprised at how quickly you come to depend on it.  Personally, I
always use revision control on my coding projects now - it's saved me
many times.

To understand what this has to do with facilitating collaboration, we'll
need to take a closer look at the mechanism that CVS provides to help
numerous people work on the same project.  But before we do that, let's
take a look at a mechanism that CVS doesn't provide (or at least,
doesn't encourage): file locking.  If you've used other version control
systems, you may be familiar with the lock-modify-unlock development
model, wherein a developer first obtains exclusive write access (a lock)
to the file to be edited, makes the changes, and then releases the lock
to allow other developers access to the file.  If someone else already
has a lock on the file, they have to "release" it before you can lock it
and start making changes (or, in some implementations, you may "steal"
their lock, but that is often an unpleasant surprise for them and not
good practice!).

This system is workable if the developers know each other, know who's
planning to do what at any given time, and can communicate with each
other quickly if someone cannot work because of access contention.
However, if the developer group becomes too large or too spread out,
dealing with all the locking issues begins to chip away at coding time;
it becomes a constant hassle that can discourage people from getting
real work done.

CVS takes a more mellow approach.  Rather than requiring that developers
coordinate with each other to avoid conflicts, CVS enables developers to
edit simultaneously, assumes the burden of integrating all the changes,
and keeps track of any conflicts.  This process uses the
copy-modify-merge model, which works as follows:

  1. Developer A requests a working copy (a directory tree containing
     the files that make up the project) from CVS.  This is also known
     as "checking out" a working copy, like checking a book out of the
     library.

  2. Developer A edits freely in her working copy.  At the same time,
     other developers may be busy in their own working copies.  Because
     these are all separate copies, there is no interference - it is as
     though all of the developers have their own copy of the same
     library book, and they're all at work scribbling comments in the
     margins or rewriting certain pages independently.

  3. Developer A finishes her changes and commits them into CVS along
     with a "log message", which is a comment explaining the nature and
     purpose of the changes.  This is like informing the library of
     what changes she made to the book and why.  The library then
     incorporates these changes into a "master" copy, where they are
     recorded for all time.

  4. Meanwhile, other developers can have CVS query the library to see
     if the master copy has changed recently.  If it has, CVS
     automatically updates their working copies.  (This part is magical
     and wonderful, and I hope you appreciate it.  Imagine how
     different the world would be if real books worked this way!)


As far as CVS is concerned, all developers on a project are equal.
Deciding when to update or when to commit is largely a matter of
personal preference or project policy.  One common strategy for coding
projects is to always update before commencing work on a major change
and to commit only when the changes are complete and tested so that the
master copy is always in a "runnable" state.

Perhaps you're wondering what happens when developers A and B, each in
their own working copy, make different changes to the same area of text
and then both commit their changes? This is called a "conflict", and
CVS notices it as soon as developer B tries to commit changes.  Instead
of allowing developer B to proceed, CVS announces that it has discovered
a conflict and places conflict markers (easily recognizable textual
flags) at the conflicting location in his copy.  That location also
shows both sets of changes, arranged for easy comparison.  Developer B
must sort it all out and commit a new revision with the conflict
resolved.  Perhaps the two developers will need to talk to each other to
settle the issue.  CVS only alerts the developers that there is a
conflict; it's up to human beings to actually resolve it.

What about the master copy? In official CVS terminology, it is called
the project's repository.  The repository is simply a file tree kept on
a central server.  Without going into too much detail about its
structure (but see *Note Repository Administration::), let's look at
what the repository must do to meet the requirements of the
checkout-commit-update cycle.  Consider the following scenario:

  1. Two developers, A and B, check out working copies of a project at
     the same time.  The project is at its starting point - no changes
     have been committed by anyone yet, so all the files are in their
     original, pristine state.

  2. Developer A gets right to work and soon commits her first batch of
     changes.

  3. Meanwhile, developer B watches television.

  4. Developer A, hacking away like there's no tomorrow, commits her
     second batch of changes.  Now, the repository's history contains
     the original files, followed by A's first batch of changes,
     followed by this set of changes.

  5. Meanwhile, developer B plays video games.

  6. Suddenly, developer C joins the project and checks out a working
     copy from the repository.  Developer C's copy reflects A's first
     two sets of changes, because they were already in the repository
     when C checked out her copy.

  7. Developer A, continuing to code as one possessed by spirits,
     completes and commits her third batch of changes.

  8. Finally, blissfully unaware of the recent frenzy of activity,
     developer B decides it's time to start work.  He doesn't bother to
     update his copy; he just commences editing files, some of which
     may be files that A has worked in.  Shortly thereafter, developer
     B commits his first changes.


At this point, one of two things can happen.  If none of the files
edited by developer B have been edited by A, the commit succeeds.
However, if CVS realizes that some of B's files are out of date with
respect to the repository's latest copies, and those files have also
been changed by B in his working copy, CVS informs B that he must do an
update before committing those files.

When developer B runs the update, CVS merges all of A's changes into B's
local copies of the files.  Some of A's work may conflict with B's
uncommitted changes, and some may not.  Those parts that don't are
simply applied to B's copies without further complication, but the
conflicting changes must be resolved by B before being committed.

If developer C does an update now, she'll receive various new changes
from the repository: those from A's third commit, and those from B's
first _successful_ commit (which might really come from B's second
attempt to commit, assuming B's first attempt resulted in B being forced
to resolve conflicts).

In order for CVS to serve up changes, in the correct sequence, to
developers whose working copies may be out of sync by varying degrees,
the repository needs to store all commits since the project's beginning.
In practice, the CVS repository stores them all as successive diffs.
Thus, even for a very old working copy, CVS is able to calculate the
difference between the working copy's files and the current state of the
repository, and is thereby able to bring the working copy up to date
efficiently.  This makes it easy for developers to view the project's
history at any point and to revive even very old working copies.

Although, strictly speaking, the repository could achieve the same
results by other means, in practice, storing diffs is a simple,
intuitive means of implementing the necessary functionality.  The
process has the added benefit that, by using patch appropriately, CVS
can reconstruct any previous state of the file tree and thus bring any
working copy from one state to another.  It can allow someone to check
out the project as it looked at any particular time.  It can also show
the differences, in diff format, between two states of the tree without
affecting someone's working copy.

Thus, the very features necessary to give convenient access to a
project's history are also useful for providing a decentralized,
uncoordinated developer team with the ability to collaborate on the
project.

For now, you can ignore the details of setting up a repository,
administering user access, and navigating CVS-specific file formats
(those will be covered in *Note Repository Administration::).  For the
moment, we'll concentrate on how to make changes in a working copy.

But first, here is a quick review of terms:

   * "Revision" A committed change in the history of a file or set of
     files.  A revision is one "snapshot" in a constantly changing
     project.

   * "Repository" The master copy where CVS stores a project's full
     revision history.  Each project has exactly one repository.

   * "Working copy" The copy in which you actually make changes to a
     project.  There can be many working copies of a given project;
     generally each developer has his or her own copy.

   * "Check out" To request a working copy from the repository.  Your
     working copy reflects the state of the project as of the moment you
     checked it out; when you and other developers make changes, you
     must use commit and update to "publish" your changes and view
     others' changes.

   * "Commit" To send changes from your working copy into the central
     repository.  Also known as "check-in".

   * "Log message" A comment you attach to a revision when you commit
     it, describing the changes.  Others can page through the log
     messages to get a summary of what's been going on in a project.

   * "Update" To bring others' changes from the repository into your
     working copy and to show if your working copy has any uncommitted
     changes.  Be careful not to confuse this with commit; they are
     complementary operations.  Mnemonic: update brings your working
     copy up to date with the repository copy.

   * "Conflict" The situation when two developers try to commit changes
     to the same region of the same file.  CVS notices and points out
     conflicts, but the developers must resolve them.



File: ossdev.info,  Node: A Day With CVS,  Next: Other Useful CVS Commands,  Prev: Basic Concepts,  Up: An Overview of CVS

A Day With CVS
==============

This section describes some basic CVS operations, then follows with a
sample session covering typical CVS usage.  As the guided tour
progresses, we'll also start to look at how CVS works internally.

Although you don't need to understand every last detail of CVS's
implementation to use it, a basic knowledge of how it works is
invaluable in choosing the best way to achieve a given result.  CVS is
more like a bicycle than an automobile, in the sense that its mechanisms
are entirely transparent to anyone who cares to look.  As with a
bicycle, you can just hop on and start riding immediately.  However, if
you take a few moments to study how the gears work, you'll be able to
ride it much more efficiently.  (In the case of CVS, I'm not sure
whether transparency was a deliberate design decision or an accident,
but it does seem to be a property shared by many free programs.
Externally visible implementations have the advantage of encouraging the
users to become contributing developers by exposing them to the system's
inner workings right from the start.)

Each part of the tour may make use of knowledge introduced in previous
parts.  Therefore, if this is your first time, I recommend that you
simply start at the beginning and take the tour sequentially, without
skipping over anything.  The menu below is merely meant as a convenience
for repeat visitors - you shouldn't use it to jump directly to a
section that interests you unless you're already familiar with the
material in the previous sections.

* Menu:

* Conventions Used In This Tour::
* Invoking CVS::
* Accessing A Repository::
* Starting A New Project::
* Checking Out A Working Copy::
* Version Versus Revision::
* Making A Change::
* Finding Out What You (And Others) Did -- update And diff::
* CVS And Implied Arguments::
* Committing::
* Revision Numbers::
* Detecting And Resolving Conflicts::
* Finding Out Who Did What (Browsing Log Messages)::
* Examining And Reverting Changes::
* The Slow Method Of Reverting::
* The Fast Method Of Reverting::


File: ossdev.info,  Node: Conventions Used In This Tour,  Next: Invoking CVS,  Up: A Day With CVS

Conventions Used In This Tour
-----------------------------

The tour takes place in a Unix environment.  CVS also runs on Windows
and Macintosh operating systems, and Tim Endres of Ice Engineering has
even written a Java client (see http://www.trustice.com/java/jcvs/),
which can be run anywhere Java runs.  However, I'm going to take a wild
guess and assume that the majority of CVS users - present and potential
- are most likely working in a Unix command-line environment.  If you
aren't one of these, the examples in the tour should be easy to
translate to other interfaces.  Once you understand the concepts, you
can sit down at any CVS front end and work with it (trust me, I've done
it many times).

The examples in the tour are oriented toward people who will be using
CVS to keep track of programming projects.  However, CVS operations are
applicable to all text documents, not just source code.

The tour also assumes that you already have CVS installed (it's present
by default on many of the popular free Unix systems, so you might
already have it without knowing it) and that you have access to a
repository.  Even if you are not set up, you can still benefit from
reading the tour.  In *Note Repository Administration::, you'll learn
how to install CVS and set up repositories.

Assuming CVS is installed, you should take a moment to find the online
CVS manual.  Known familiarly as the "Cederqvist" (after Per Cederqvist,
its original author), it comes with the CVS source distribution and is
usually the most up-to-date reference available.  It's written in
Texinfo format and should be available on Unix systems in the "Info"
documentation hierarchy.  You can read it either with the command line
info program

     floss$ info cvs

or by pressing Ctrl+H and then typing "i" inside Emacs.  If neither of
these works for you, consult your local Unix guru (or see *Note
Repository Administration:: regarding installation issues).  You'll
definitely want to have the Cederqvist at your fingertips if you're
going to be using CVS regularly.


File: ossdev.info,  Node: Invoking CVS,  Next: Accessing A Repository,  Prev: Conventions Used In This Tour,  Up: A Day With CVS

Invoking CVS
------------

CVS is one program, but it can perform many different actions: updating,
committing, branching, diffing, and so on.  When you invoke CVS, you
must specify which action you want to perform.  Thus, the format of a
CVS invocation is:

     floss$ cvs command

For example, you can use

     floss$ cvs update
     floss$ cvs diff
     floss$ cvs commit

and so on.  (Don't bother to try running any of those particular
commands yet, though; they won't do anything until you're in a working
copy, which we'll get to shortly.)

Both CVS and the command can take options.  Options that affect the
behavior of CVS, independently of the command being run, are called
global options; command-specific options are just called command
options.  Global options always go to the left of the command; command
options, to its right.  So in

     floss$ cvs -Q update -p

-Q is a global option, and -p is a command option.  (If you're curious,
-Q means "quietly"-that is, suppress all diagnostic output, and print
error messages only if the command absolutely cannot be completed for
some reason; -p means to send the results of update to standard output
instead of to files.)


File: ossdev.info,  Node: Accessing A Repository,  Next: Starting A New Project,  Prev: Invoking CVS,  Up: A Day With CVS

Accessing A Repository
----------------------

Before you can do anything, you must tell CVS the location of the
repository you'll be accessing.  This isn't a concern if you already
have a working copy checked out - any working copy knows what
repository it came from, so CVS can automatically deduce the repository
for a given working copy.  However, let's assume you don't have a
working copy yet, so you need to tell CVS explicitly where to go.  This
is done with the -d global option (the -d stands for "directory", an
abbreviation for which there is a historical justification, although -r
for "repository" might have been better), followed by the path to the
repository.  For example, assuming the repository is on the local
machine in /usr/local/cvs (a fairly standard location):

     floss$ cvs -d /usr/local/cvs command

In many cases, however, the repository is on another machine and must
therefore be reached over the network.  CVS provides a choice of network
access methods; which one you'll use depends mostly on the security
needs of the repository machine (hereinafter referred to as "the
server").  Setting up the server to allow various remote access methods
is covered in *Note Repository Administration::; here we'll deal only
with the client side.

Fortunately, all the remote access methods share a common invocation
syntax.  In general, to specify a remote repository as opposed to a
local one, you just use a longer repository path.  You first name the
access method, delimited on each side by colons, followed by the
username and the server name (joined with an @ sign), another separator
colon, and finally the path to the repository directory on the server.

Let's look at the "pserver" access method, which stands for
"password-authenticated server":

     floss$ cvs -d :pserver:jrandom@cvs.foobar.com:/usr/local/cvs login
     (Logging in to jrandom@cvs.foobar.com)
     CVS password: (enter your CVS password here)
     floss$

The long repository path following -d told CVS to use the pserver access
method, with the username jrandom, on the server cvs.foobar.com, which
has a CVS repository in /usr/local/cvs.  There's no requirement that the
hostname be "cvs.something.com" by the way; that's a common convention,
but it could just as easily have been:

     floss$ cvs -d :pserver:jrandom@fish.foobar.org:/usr/local/cvs command

The command actually run was login, which verifies that you are
authorized to work with this repository.  It prompts for a password,
then contacts the server to verify the password.  Following Unix custom,
cvs login returns silently if the login succeeds; it shows an error
message if it fails (for instance, because the password is incorrect).

You only have to log in once from your local machine to a given CVS
server.  After a successful login, CVS stores the password in your home
directory, in a file called .cvspass.  It consults that file every time
a repository is contacted via the pserver method, so you only have to
run login the first time you access a given CVS server from a particular
client machine.  Of course, you can rerun cvs login anytime if the
password changes.

Note: pserver is currently the only access method requiring an initial
login like this; with the others, you can start running regular CVS
commands immediately.

Once you've stored the authentication information in your .cvspass file,
you can run other CVS commands using the same command-line syntax:

     floss$ cvs -d :pserver:jrandom@cvs.foobar.com:/usr/local/cvs command

Getting pserver to work in Windows may require an extra step.  Windows
doesn't have the Unix concept of a home directory, so CVS doesn't know
where to put the .cvspass file.  You'll have to specify a location.
It's normal to designate the root of the C: drive as the home directory:

     C:\WINDOWS> set HOME=C:
     C:\WINDOWS> cvs -d :pserver:jrandom@cvs.foobar.com:/usr/local/cvs login
     (Logging in to jrandom@cvs.foobar.com)
     CVS password: (enter password here)
     C:\WINDOWS>

Any folder in the file system will suffice.  You may want to avoid
network drives, though, because the contents of your .cvspass file would
then be visible to anyone with access to the drive.

In addition to pserver, CVS supports the ext method (which uses an
external connection program, such as rsh or ssh), kserver (for the
Kerberos security system version 4), and gserver (which uses the GSSAPI,
or Generic Security Services API, and also handles Kerberos versions 5
and higher).  These methods are similar to pserver, but each has its own
idiosyncrasies.

Of these, the `ext' method is probably the most commonly used.  If you
can log into the server with rsh or ssh, you can use the `ext' method.
You can test it like this:

     floss$ rsh -l jrandom cvs.foobar.com
     Password: enter your login password here

Okay, let's assume you successfully logged in and logged out of the
server with rsh, so now you're back on the original client machine:

     floss$ CVS_RSH=rsh; export CVS_RSH
     floss$ cvs -d :ext:jrandom@cvs.foobar.com:/usr/local/cvs command

The first line sets (in Unix Bourne shell syntax) the CVS_RSH
environment variable to rsh, which tells CVS to use the rsh program to
connect.  The second line can be any CVS command; you will be prompted
for your password so CVS can log into the server.

If you're in C shell rather than in Bourne shell, try this:

     floss% setenv CVS_RSH rsh

and for Windows, try this:

     C:\WINDOWS> set CVS_RSH=rsh

The rest of the tour will use the Bourne syntax; translate for your
environment as necessary.

To use ssh (the Secure Shell) instead of rsh, just set the CVS_RSH
variable appropriately:

     floss$ CVS_RSH=ssh; export CVS_RSH

Don't get thrown by the fact that the variable's name is CVS_RSH but
you're setting its value to ssh.  There are historical reasons for this
(the catch-all Unix excuse, I know).  CVS_RSH can point to the name of
any program capable of logging you into the remote server, running
commands, and receiving their output.  After rsh, ssh is probably the
most common such program, although there are probably others.  Note that
this program must not modify its data stream in any way.  This
disqualifies the Windows NT rsh, because it converts (or attempts to
convert) between the DOS and Unix line-ending conventions.  You'd have
to get some other rsh for Windows or use a different access method.

The gserver and kserver methods are not used as often as the others and
are not covered here.  They're quite similar to what we've covered so
far; see the Cederqvist for details.

If you only use one repository and don't want to type -d repos each
time, just set the CVSROOT environment variable (which perhaps should
have been named CVSREPOS, but it's too late to change that now):

     floss$ CVSROOT=/usr/local/cvs
     floss$ export CVSROOT
     floss$ echo $CVSROOT
     /usr/local/cvs
     floss$

or maybe

     floss$ CVSROOT=:pserver:jrandom@cvs.foobar.com:/usr/local/cvs
     floss$ export CVSROOT
     floss$ echo $CVSROOT
     :pserver:jrandom@cvs.foobar.com:/usr/local/cvs
     floss$

The rest of this tour assumes that you've set CVSROOT to point to your
repository, so the examples will not show the -d option.  If you need to
access many different repositories, you should not set CVSROOT and
should just use -d repos when you need to specify the repository.


File: ossdev.info,  Node: Starting A New Project,  Next: Checking Out A Working Copy,  Prev: Accessing A Repository,  Up: A Day With CVS

Starting A New Project
----------------------

If you're learning CVS in order to work on a project that's already
under CVS control (that is, it is kept in a repository somewhere),
you'll probably want to skip down to the next section, "Checking Out A
Working Copy." On the other hand, if you want to take existing source
code and put it into CVS, this is the section for you.  Note that it
still assumes you have access to an existing repository; see *Note
Repository Administration:: if you need to set up a repository first.

Putting a new project into a CVS repository is known as "importing".
The CVS command, as you may have guessed, is

     floss$ cvs import

except that it needs some more options (and needs to be in the right
location) to succeed.  First, go into the top-level directory of your
project tree:

     floss$ cd myproj
     floss$ ls
     README.txt  a-subdir/   b-subdir/   hello.c
     floss$

This project has two files - README.txt and hello.c - in the top level,
plus two subdirectories - a-subdir and b-subdir - plus some more files
(not shown in the example) inside those subdirectories.  When you
import a project, CVS imports everything in the tree, starting from the
current directory and working its way down.  Therefore, you should make
sure that the only files in the tree are ones you want to be permanent
parts of the project.  Any old backup files, scratch files, and so on
should all be cleaned out.

The general syntax of an import command is

     floss$ cvs import -m "log msg" projname vendortag releasetag

The -m flag (for message) is for specifying a short message describing
the import.  This will be the first log message for the entire project;
every commit thereafter will also have its own log message.  These
messages are mandatory; if you don't give the -m flag, CVS automatically
starts up an editor (by consulting the EDITOR environment variable) for
you to type a log message in.  After you save the log message and exit
the editor, the import then continues.

The next argument is the project's name (we'll use "myproj").  This is
the name under which you'll check out the project from the repository.
(What actually happens is that a directory of that name gets created in
the repository, but more on that in *Note Repository Administration::.)
The name you choose now does not need to be the same as the name of the
current directory, although in most cases it usually is.

The vendortag and releasetag arguments are a bit of bookkeeping for CVS.
Don't worry about them now; it hardly matters what you use.  In *Note
Advanced CVS:: you'll learn about the rare circumstances where they're
significant.  For now, we'll use a username and "start" for those
arguments.

We're ready to run import:

     floss$ cvs import -m "initial import into CVS" myproj jrandom start
     N myproj/hello.c
     N myproj/README.txt
     cvs import: Importing /usr/local/cvs/myproj/a-subdir
     N myproj/a-subdir/whatever.c
     cvs import: Importing /usr/local/cvs/myproj/a-subdir/subsubdir
     N myproj/a-subdir/subsubdir/fish.c
     cvs import: Importing /usr/local/cvs/myproj/b-subdir
     N myproj/b-subdir/random.c
     
     No conflicts created by this import
     floss$

Congratulations! If you ran that command (or something similar), you've
finally done something that affects the repository.

Reading over the output of the import command, you'll notice that CVS
precedes each filename with a single letter - in this case, "N" for
"new file". The use of a single letter on the left to indicate the
status of a file is a general pattern in CVS command output.  We'll see
it later in checkout and update as well.

You might think that, having just imported the project, you can start
working in the tree immediately.  This is not the case, however.  The
current directory tree is still not a CVS working copy.  It was the
source for the import command, true, but it wasn't magically changed
into a CVS working copy merely by virtue of having been imported.  To
get a working copy, you need to check one out from the repository.

First, though, you might want to archive the current project tree.  The
reason is that once the sources are in CVS, you don't want to confuse
yourself by accidentally editing copies that aren't in version control
(because those changes won't become part of the project's history).  You
want to do all of your editing in a working copy from now on.  However,
you also don't want to remove the imported tree entirely, because you
haven't yet verified that the repository actually has the files.  Of
course, you can be 99.999 percent certain that it does because the
import command returned with no error, but why take chances? Paranoia
pays, as every programmer knows.  Therefore, do something like this:

     floss$ ls
     README.txt  a-subdir/   b-subdir/   hello.c
     floss$ cd ..
     floss$ ls
     myproj/
     floss$ mv myproj was_myproj
     floss$ ls
     was_myproj/
     floss$

There.  You still have the original files, but they're clearly named as
an obsolete version, so they won't be in the way when you get a real
working copy.  Now you're ready to check out.


File: ossdev.info,  Node: Checking Out A Working Copy,  Next: Version Versus Revision,  Prev: Starting A New Project,  Up: A Day With CVS

Checking Out A Working Copy
---------------------------

The command to check out a project is exactly what you think it is:

     floss$ cvs checkout myproj
     cvs checkout: Updating myproj
     U myproj/README.txt
     U myproj/hello.c
     cvs checkout: Updating myproj/a-subdir
     U myproj/a-subdir/whatever.c
     cvs checkout: Updating myproj/a-subdir/subsubdir
     U myproj/a-subdir/subsubdir/fish.c
     cvs checkout: Updating myproj/b-subdir
     U myproj/b-subdir/random.c
     
     floss$ ls
     myproj/      was_myproj/
     floss$ cd myproj
     floss$ ls
     CVS/        README.txt  a-subdir/   b-subdir/   hello.c
     floss$

Behold - your first working copy! Its contents are exactly the same as
what you imported, with the addition of a subdirectory named "CVS".
That's where CVS stores version control information.  Actually, each
directory in the project has a CVS subdirectory:

     floss$ ls a-subdir
     CVS/        subsubdir/  whatever.c
     floss$ ls a-subdir/subsubdir/
     CVS/    fish.c
     floss$ ls b-subdir
     CVS/      random.c

The fact that CVS keeps its revision information in subdirectories named
CVS means that your project can never contain subdirectories of its own
named CVS.  In practice, I've never heard of this being a problem.

Before editing any files, let's take a peek inside the black box:

     floss$ cd CVS
     floss$ ls
     Entries     Repository  Root
     floss$ cat Root
     /usr/local/cvs
     floss$ cat Repository
     myproj
     floss$

Nothing too mysterious there.  The Root file points to repository, and
the Repository file points to a project inside the repository.  If
that's a little confusing, let me explain.

There is a longstanding confusion about terminology in CVS.  The word
"repository" is used to refer to two different things.  Sometimes, it
means the root directory of a repository (for example, /usr/local/cvs),
which can contain many projects; this is what the Root file refers to.
But other times, it means one particular project-specific subdirectory
within a repository root (for example, /usr/local/cvs/myproj,
/usr/local/cvs/yourproj, or /usr/local/cvs/fish).  The Repository file
inside a CVS subdirectory takes the latter meaning.

In this book, "repository" generally means Root (that is, the top-level
repository), although it may occasionally be used to mean a
project-specific subdirectory.  If the intended sense can't be figured
out from the context, there will be clarifying text.  Note that the
Repository file may sometimes contain an absolute path to the project
name instead of a relative path.  This can make it slightly redundant
with the Root file:

     floss$ cd CVS
     floss$ cat Root
     :pserver:jrandom@cvs.foobar.com:/usr/local/cvs
     floss$ cat Repository
     /usr/local/cvs/myproj
     floss$

The Entries file stores information about the individual files in the
project.  Each line deals with one file, and there are only lines for
files or subdirectories in the immediate parent directory.  Here's the
top-level CVS/Entries file in myproj:

     floss$ cat Entries
     /README.txt/1.1.1.1/Sun Apr 18 18:18:22 1999//
     /hello.c/1.1.1.1/Sun Apr 18 18:18:22 1999//
     D/a-subdir////
     D/b-subdir////

The format of each line is

     /filename/revision number/last modification date//

and the directory lines are prefixed with "D". (CVS doesn't really keep
a change history for directories, so the fields for revision number and
datestamp are empty.)

The datestamps record the date and time of the last update (in Universal
Time, not local time) of the files in the working copy.  That way, CVS
can easily tell whether a file has been modified since the last
checkout, update, or commit.  If the file system timestamp differs from
the timestamp in the CVS/Entries file, CVS knows (without even having to
consult the repository) that the file was probably modified.

If you take a look at the CVS/* files in one of the subdirectories

     floss$ cd a-subdir/CVS
     floss$ cat Root
     /usr/local/cvs
     floss$ cat Repository
     myproj/a-subdir
     floss$ cat Entries
     /whatever.c/1.1.1.1/Sun Apr 18 18:18:22 1999//
     D/subsubdir////
     floss$

you can see that the root repository has not changed, but the Repository
file spells out the location of this subdirectory of the project, and
the Entries file contains different lines.

Immediately after import, the revision number of every file in the
project is shown as 1.1.1.1.  This initial revision number is a bit of a
special case, so we won't examine it in detail just yet; we'll take a
closer look at revision numbers after we've committed some changes.


File: ossdev.info,  Node: Version Versus Revision,  Next: Making A Change,  Prev: Checking Out A Working Copy,  Up: A Day With CVS

Version Versus Revision
-----------------------

The internal revision number that CVS keeps for each file is unrelated
to the version number of the software product of which the files are
part.  For example, you may have a project composed of three files,
whose internal revision numbers on May 3, 1999, were 1.2, 1.7, and 2.48.
On that day, you package up a new release of the software and release it
as SlickoSoft Version 3.  This is purely a marketing decision and
doesn't affect the CVS revisions at all.  The CVS revision numbers are
invisible to your customers (unless you give them repository access);
the only publicly visible number is the "3" in Version 3.  You could
have called it Version 1729 as far as CVS is concerned - the version
number (or "release" number) has nothing to do with CVS's internal
change tracking.

To avoid confusion, I'll use the word "revision" to refer exclusively to
the internal revision numbers of files under CVS control.  I may still
call CVS a "version control system", however, because "revision control
system" just sounds too awkward.


File: ossdev.info,  Node: Making A Change,  Next: Finding Out What You (And Others) Did -- update And diff,  Prev: Version Versus Revision,  Up: A Day With CVS

Making A Change
---------------

The project as it stands doesn't do much.  Here are the contents of
hello.c:

     floss$ cat hello.c
     #include <stdio.h>
     
     void
     main ()
     {
        printf ("Hello, world!\n");
     }

Let's make the first change to the project since importing it; we'll add
the line

     printf ("Goodbye, world!\n");

right after the Hello, world!.  Invoke your favorite editor and make the
change:

     floss$ emacs hello.c
       ...

This was a fairly simple change, one where you're not likely to forget
what you did.  But in a larger, more complex project, it's quite
possible you may edit a file, be interrupted by something else, and
return several days later and be unable to remember exactly what you
did, or even to remember if you changed anything at all.  Which brings
us to our first "CVS Saves Your Life" situation: comparing your working
copy against the repository.

