wincvs Users Guide 

Step by step cook book.

http://cvsgui.sourceforge.net/winhtml/wincvs11.htm

CVS Best Practices 

This article explores some of the best practices that can be adopted while using CVS as the configuration management tool in your software projects.

http://www.magic-cauldron.com/ http://www.magic-cauldron.com/cm/cvs-bestpractices/index-cvs-bestpractices.html http://www.linuxdoc.org/REF/CVS-BestPractices/CVS-BestPractices.html.tar.gz

Open Source Development With 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.

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.

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

Finding Out What You (And Others) Did - update And diff 

Previously, I've talked about updating as a way of bringing changes down from the repository into your working copy - that is, as a way of getting other people's changes. However, update is really a bit more complex; it compares the overall state of the working copy with the state of the project in the repository. Even if nothing in the repository has changed since checkout, something in the working copy may have, and update will show that, too:

floss$ cvs update
cvs update: Updating .
M hello.c
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
cvs update: Updating b-subdir

The M next to hello.c means the file has been modified since it was last checked out, and the modifications have not yet been committed to the repository.

Sometimes, merely knowing which files you've edited is all you need. However, if you want a more detailed look at the changes, you can get a full report in diff format. The diff command compares the possibly modified files in the working copy to their counterparts in the repository and displays any differences:

floss$ cvs diff
cvs diff: Diffing .
Index: hello.c
===================================================================
RCS file: /usr/local/cvs/myproj/hello.c,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 hello.c
6a7
>   printf ("Goodbye, world!\n");
cvs diff: Diffing a-subdir
cvs diff: Diffing a-subdir/subsubdir
That's  helpful, if a bit obscure, but there's still a lot of cruft in
the  output. For starters, you can ignore most of the first few lines.
They  just  name  the  repository file and give the number of the last
checked-in  revision.  These  are  useful  pieces of information under
other  circumstances  (we'll look more closely at them later), but you
don't need them when you're just trying to get a sense of what changes
have been made in the working copy.
A  more  serious  impediment  to  reading  the  diff  is  that  CVS is
announcing its entry as it goes into each directory during the update.
This  can be useful during long updates on large projects, as it gives
you  a  sense  of how much longer the command will take, but right now
it's just getting in the way of reading the diff. Let's tell CVS to be
quiet about where it's working, with the -Q global option:
floss$ cvs -Q diff
Index: hello.c
===================================================================
RCS file: /usr/local/cvs/myproj/hello.c,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 hello.c
6a7
>   printf ("Goodbye, world!\n");

CVS And Implied Arguments 

In each of the CVS commands so far, you may have noticed that no files were specified on the command line. We ran

floss$ cvs diff

instead of

floss$ cvs diff hello.c

and

floss$ cvs update

instead of

floss$ cvs update hello.c

The principle at work here is that if you don't name any files, CVS acts on all files for which the command could possibly be appropriate. This even includes files in subdirectories beneath the current directory; CVS automatically descends from the current directory through every subdirectory in the tree. For example, if you modified b-subdir/random.c and a-subdir/subsubdir/fish.c, running update may result in this:

floss$ cvs update
cvs update: Updating .
M hello.c
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
M a-subdir/subsubdir/fish.c
cvs update: Updating b-subdir
M b-subdir/random.c
floss$

or better yet:

floss$ cvs -q update
M hello.c
M a-subdir/subsubdir/fish.c
M b-subdir/random.c
floss$

Note: The -q flag is a less emphatic version of -Q. Had we used -Q, the command would have printed out nothing at all, because the modification notices are considered nonessential informational messages. Using the lowercase -q is less strict; it suppresses the messages we probably don't want, while allowing certain, more useful messages to pass through.

You can also name specific files for the update:

floss$ cvs update hello.c b-subdir/random.c
M hello.c
M b-subdir/random.c
floss$

and CVS will only examine those files, ignoring all others.

In truth, it's more common to run update without restricting it to certain files. In most situations, you'll want to update the entire directory tree at once. Remember, the updates we're doing here only show that some files have been locally modified, because nothing has changed yet in the repository. When other people are working on the project with you, there's always the chance that running update will pull some new changes down from the repository and incorporate them into your local files. In that case, you may find it slightly more useful to name which files you want updated.

The same principle can be applied to other CVS commands. For example, with diff, you can choose to view the changes one file at a time

floss$ cvs diff -c b-subdir/random.c

CVS—Concurrent Versions System 

http://www.gnu.org/manual/cvs/html_node/cvs_toc.html

Very good user manual, for example, its "Multiple developers" chapter contains:

and talks about how to unedit a file.

A sample session 

As a way of introducing cvs, we'll go through a typical work-session using cvs. The first thing to understand is that cvs stores all files in a centralized repository (see Chapter 2 [Repository], page 7); this section assumes that a repository is set up.

Suppose you are working on a simple compiler. The source consists of a handful of C files and a `Makefile'. The compiler is called `tc' (Trivial Compiler), and the repository is set up so that there is a module called `tc'.

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

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 Chapter 10 [Multiple developers], page 63, for an explanation.

The checkout command can either take a module name as argument or a path name relative to $CVSROOT, as the following wdir example.

Committing your changes 

When you have checked that the compiler is still compilable you decide to make a new version of `backend.c'. This will store your new `backend.c' in the repository and make it available to anyone else who is using that same repository. $ cvs commit backend.c cvs starts an editor, to allow you to enter a log message. You type in \Added an optimiza- tion pass.", save the temporary file, and exit the editor.

The environment variable $CVSEDITOR determines which editor is started. If $CVSEDITOR is not set, then if the environment variable $EDITOR is set, it will be used. If both $CVSEDITOR and $EDITOR are not set then there is a default which will vary with your operating system, for example vi for unix or notepad for Windows NT/95.

In addition, cvs checks the $VISUAL environment variable. Opinions vary on whether this behavior is desirable and whether future releases of cvs should check $VISUAL or ignore it. You will be OK either way if you make sure that $VISUAL is either unset or set to the same thing as $EDITOR.

When cvs starts the editor, it includes a list of files which are modified. For the cvs client, this list is based on comparing the modification time of the file against the mod- ification time that the file had when it was last gotten or updated. Therefore, if a file's modification time has changed but its contents have not, it will show up as modified. The simplest way to handle this is simply not to worry about it|if you proceed with the commit cvs will detect that the contents are not modified and treat it as an unmodified file. The next update will clue cvs in to the fact that the file is unmodified, and it will reset its stored timestamp so that the file will not show up in future editor sessions.

If you want to avoid starting an editor you can specify the log message on the command line using the `-m' flag instead, like this:

$ cvs commit -m "Added an optimization pass" backend.c

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 A.15 [release], page 112):

$ cd ..
$ cvs release -d tc
M driver.c
? tc
You have [1] altered files in this repository.
Are you sure you want to release (and delete) directory `tc': n
** `release' aborted by user choice.

The release command checks that all your modifications have been committed. If history logging is enabled it also makes a note in the history file. See Section C.11 [history file], page 140.

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 C.9 [cvsignore], page 138, for information about how to make that warning go away. See Section A.15.2 [release output], page 112, 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' 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) directory `tc': y