Go to the previous, next section.
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.
This is a list of the keywords that RCS currently (in release 5.6.0.1) supports:
$Author$
$Date$
$Header$
$Id$
$Header$
, except that the RCS
filename is without a path.
$Locker$
$Log$
$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$
$Revision$
$Source$
$State$
cvs admin -s
---See section admin options.
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 $";
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.
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.
Each file has a stored default substitution mode, and
each working directory copy of a file also has a
substitution mode. The former is set by the `-k'
option to cvs add
and cvs admin
; the
latter is set by the -k or -A options to cvs
checkout
or cvs update
. cvs diff
also
has a `-k' option. For some examples,
See section Handling binary files.
The modes available are:
$
Revision: 5.7 $ for the Revision
keyword.
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.
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.
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.
One often would like to use `-kv' with cvs
export
---see section export--Export sources from CVS, similar to checkout. But be aware that doesn't
handle an export containing binary files correctly.
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.
Go to the previous, next section.