1170 lines
41 KiB
Plaintext
1170 lines
41 KiB
Plaintext
\input texinfo
|
||
@setfilename rcs
|
||
@setchapternewpage odd
|
||
@settitle Using RCS
|
||
@titlepage
|
||
@sp 6
|
||
@center @titlefont{A guide to using RCS}
|
||
@sp 1
|
||
@center Pete Ware
|
||
@end titlepage
|
||
@page
|
||
|
||
@chapter What RCS does
|
||
|
||
RCS stands for Revision Control System and is made of seven programs:
|
||
@code{ci}, @code{co}, @code{rcs}, @code{rcsmerge}, @code{rcsdiff},
|
||
@code{ident}, and @code{rlog}. In addition, @code{make} knows about RCS
|
||
and is able to interact with RCS. Files under RCS management are
|
||
distuingished by having a @file{,v} appended to the name of the file.
|
||
These files should be considered private to RCS, even though they are
|
||
normal ascii files. It is common for each working directory to have a
|
||
directory called @file{RCS} with all the files private to RCS kept
|
||
there. This helps minimize on the number of files in your working
|
||
directory.
|
||
|
||
Using RCS means a change in behaviour, which is annoying to some, but
|
||
unavoidable. You @strong{must} learn two things: to check out a file
|
||
before changing it and to check the file back in after changes are made.
|
||
|
||
@section Keeps track of changes
|
||
|
||
This is the primary purpose of RCS. Each time you change a file and
|
||
check the file back into RCS, RCS calculates the minimum number of lines
|
||
that have changed between the earlier revision and the revision you just
|
||
checked in. It saves these differences so that you can recover an
|
||
earlier version. Since only the differences between the two revisions
|
||
are saved, there is not much wasted space.
|
||
|
||
You can compare any two revisions of the file. This is especially
|
||
useful if you have just made some changes that introduced a bug and are
|
||
curious to see what is different between the current version and
|
||
previous one. You can recover any revision of a file, from the original
|
||
source up to the current version.
|
||
|
||
You are even protected against stupid mistakes like @samp{rm *.c}, since
|
||
you can recover these files up to the time of the last revision. To
|
||
take advantage of this you must make small, incremental changes and
|
||
check each file back into RCS when you are done.
|
||
|
||
@section Allows sharing of source files
|
||
|
||
As more people work on a project, it becomes more likely that two people
|
||
are going to make changes to the same file at the same time -- one of
|
||
you is going to lose. RCS avoids this problem by requiring that you
|
||
first @emph{lock} a file prior to editing it; only one person can have a
|
||
lock at a time. The above is called @dfn{access control}.
|
||
|
||
Since RCS can keep its files in a subdirectory called @file{RCS} of your
|
||
working directory, it is easy to allow multiple references to the source
|
||
code. This is done by creating a @dfn{soft link} with the command
|
||
@samp{ln -s} to the @file{RCS} directory itself. RCS then thinks this
|
||
is a normal @file{RCS} directory and allows you access to the files
|
||
contained in it (subject to the above mentioned access control). This
|
||
ability is very practical when it comes to preparing a version of the
|
||
software for testing without disturbing other developers efforts.
|
||
|
||
@section Maintains Log
|
||
|
||
Everytime you check a file into RCS, you are prompted for a log message.
|
||
This is an excellent chance to enter a one or two line message
|
||
describing the changes in this revision. It is unfortunate, but you
|
||
can enter empty log messages -- however, if you can't take the 30
|
||
seconds to describe what you've done, why did you do it?
|
||
|
||
RCS also notes the author of the changes and the date and time. This
|
||
information can be stored and updated automatically in the
|
||
text of your file.
|
||
|
||
@section RCS and @code{make}
|
||
|
||
@code{make} knows about RCS and how to get files from it. If a source
|
||
file is missing, @code{make} looks for the corresponding RCS file and
|
||
performs a check out. @code{make} also checks if the RCS file is more
|
||
recent then the current file and attempts to check it out if it is.
|
||
Everytime @code{make} checks a file out, it sets the time stamp on the
|
||
file to be the same as the RCS file. This causes the dependencies
|
||
between RCS files, source files and object files (@file{.o}'s) to
|
||
maintain the correct relationship. Also, an object (@file{.o}) file will
|
||
not be recompiled if the RCS version has not changed, even if
|
||
@code{make} had to check it out from RCS to find the file. When
|
||
@code{make} is finished, it removes any files it had to check out from
|
||
RCS.
|
||
|
||
In other words, @code{make} may seem to be checking out a lot of files
|
||
from RCS, but they are not being recompiled.
|
||
|
||
@emph{This is not available with all versions of make, nor on all
|
||
computers!} For instance, GNU @code{make}, version 3.62, has this
|
||
capability. Others may or may not, and it is best to check the
|
||
documentation for the version of @code{make} that you have.
|
||
|
||
@section Other Code Maintenance Facilities
|
||
|
||
Other programs useful for code maintenance are:
|
||
|
||
@table @code
|
||
@item SCCS
|
||
Unfortunately, @code{SCCS} is not free. Furthermore, @code{SCCS} does
|
||
not provide for symbolic names.
|
||
|
||
@item CVS
|
||
CVS is a front-end for RCS that allows parallel development:
|
||
Many people can work on the same source at once, and it provides for
|
||
parallel development in an orderly way. It also allows you to manage an
|
||
entire directory tree at once rather than each level of the directory
|
||
tree seperately.
|
||
|
||
CVS is available as
|
||
@code{prep.ai.mit.edu:/pub/gnu/cvs-@var{version}.tar.Z}, and is under
|
||
the GNU copyleft. @var{version} as of this writing is 1.3.
|
||
@end table
|
||
|
||
@chapter Abuse of RCS
|
||
|
||
RCS takes care of all the items that you would want of a revision
|
||
control system. What it cannot do is make sure you use it correctly.
|
||
There are a couple typical ways that RCS is misused: checking out each
|
||
and every file with a lock; working for days, weeks or months on one
|
||
revision without checking the file back in; and not adding log messages.
|
||
|
||
Checking out (with a lock) every file is an easy way to pretend that RCS
|
||
does not exist. Then when somebody wants to build a version of the
|
||
software, you just check every file into RCS. This will work, but you
|
||
are missing all of the ability to share sources and avoid trouble with
|
||
access control. I @emph{prefer} the extra step needed to check out
|
||
a file with a lock before editing it. It makes me think a little before
|
||
hacking away at the source and makes it simple (maybe even possible) to
|
||
back out my changes if they are not correct. There is nothing wrong
|
||
with having all your files checked out at once, as long as they are not
|
||
locked.
|
||
|
||
It is not that keeping a file checked out with a lock for a long time is
|
||
bad, just that it indicates you are making many changes without
|
||
providing any way of undoing the last change. There is a lot to be said
|
||
for small, incremental changes with a chance to test each change to make
|
||
sure things work. When something breaks, you know it was the last
|
||
incremental change, instead of one of the last 15 modifications you
|
||
made. The rule of thumb for determining when to check something back in
|
||
is:
|
||
@quotation
|
||
How much of the changes you made are you willing to lose and how much
|
||
work is it going to be to undo those changes if it was a mistake?
|
||
@end quotation
|
||
|
||
Log messages are very helpful to other people to document the changes
|
||
you have made. They are somewhat useful when you compare two revisions
|
||
for differences because the log message documents those changes. It
|
||
only takes a small amount of effort, especially when compared to the
|
||
effort needed for making the changes.
|
||
|
||
@chapter Basic RCS commands
|
||
|
||
There are two commands that are used on a regular basis, @code{ci}
|
||
(``check-in'') and @code{co} (``check-out''). The following sections
|
||
provide some tutorials on using the different options. The manual pages
|
||
are the typically concise Unix manual pages -- but they are accurate.
|
||
It is useful to have the manual pages in front of you as you go through
|
||
this to correlate the language in the manual with the examples that
|
||
follow.
|
||
|
||
@section Definitions
|
||
|
||
It is time to explicitly define the terminology. It is
|
||
straight-forward, although somehow confusion arises when actually doing
|
||
things.
|
||
|
||
@table @dfn
|
||
|
||
@item Delta
|
||
@itemx Revision
|
||
A @samp{delta} or revision is created everytime you check a file back into
|
||
RCS. The differences between the revision you are checking in and the
|
||
previous revision are calculated. The revision you check in is given a
|
||
unique revision number so you can retrieve it later. These differences
|
||
are the @samp{delta}.
|
||
|
||
@item Check in
|
||
When you are finished with a set of changes, you check the file back into
|
||
RCS using the @code{ci} command. To be able to check something in, you
|
||
must have locked the file first or you must be creating the RCS file for
|
||
the first time.
|
||
|
||
@item Check out
|
||
You check a file out from RCS when you want to use it. You can either
|
||
check a file out as locked or unlocked. You can get particular
|
||
revisions of the file but by default you get the most recent revision.
|
||
When a file is checked out, certain keywords are filled in.
|
||
|
||
@item Locked
|
||
@itemx Unlocked
|
||
Locked and unlocked are the two ways you can check out a file. A file
|
||
checked out unlocked will not have write permission on it. If you
|
||
intend to change a file (i.e. edit the file) then you should check it
|
||
out locked. Only one person at a time may have a lock on a file, this
|
||
prevents simultaneous updates. If you want to compile the file, search
|
||
for something, print it or anything else that does not involve changing
|
||
the file, you should check it out unlocked.
|
||
|
||
@item Revision Numbering
|
||
Each time you check a file into RCS, it is assigned a unique revision
|
||
number (among other things). RCS attempts to maintain a @dfn{tree} of
|
||
revisions. Usually (99% of the time) it is just a straight tree without
|
||
any branches. Knowing or understanding the number scheme is not that
|
||
important, so skip the next paragraph if you are not interested in such
|
||
arcane knowledge.
|
||
|
||
The main trunk of the tree has numbers with two fields (like @samp{1.1}
|
||
or @samp{2.3}). Each branch from the main trunk has an additional two
|
||
fields suffixed to the version it branched off from. For example if you
|
||
created a branch from revision @samp{2.3} it would initially be called
|
||
revision @samp{2.3.1.1}. Branches can sprout further branches in which
|
||
case an additional pair of fields is added to the name (ad infinitum,
|
||
although ad nauseum is more appropriate because you would be very sick
|
||
and confused if you had branches with branches with branches). RCS
|
||
automatically increments the second field of the last pair of numbers.
|
||
If you want to change the first field (from 1.x to 2.0) you must do so
|
||
explicitly.
|
||
|
||
@item Symbolic Names.
|
||
This is a very important feature for software configuration management
|
||
and is the big win that RCS has over SCCS. It allows you to assign a
|
||
word to stand for a particular revision of a file. Since some files
|
||
require more changes than others, revision numbers never match up.
|
||
Instead you assign a symbolic name, such as Version2, to the appropriate
|
||
revision of each file. Then you can use the symbolic name Version2 to
|
||
refer to the sources that make up the second version of this program.
|
||
|
||
@item Soft (symbolic) Links
|
||
Soft links are a method that Unix uses to reference another file or
|
||
directory. They are created with the command @samp{ln -s orig-file
|
||
symbolic-name}.
|
||
|
||
@end table
|
||
|
||
@section Check out
|
||
|
||
Once a file is under RCS control, you can get access to it for either
|
||
reading or writing. If you only intend to print the file, compile it,
|
||
search for something, etc, you should check it out unlocked. If you
|
||
want to change the file, check it out locked. Usually, just check a
|
||
file out unlocked.
|
||
|
||
To check out a file without a lock, just say
|
||
@example
|
||
co test.c
|
||
@end example
|
||
this retrieves the most recent revision of the file (obtained from
|
||
@file{RCS/test.c,v}) and deposits it in your current directory. The
|
||
access permission on the file is read only. This is a reminder
|
||
that the file is not locked, and prevent users
|
||
from changing the file (Note: you could do @samp{chmod u+w file.c}, but
|
||
in that case why not just check it out locked?).
|
||
|
||
To check out a file with a lock:
|
||
@example
|
||
co -l test.c
|
||
@end example
|
||
the @samp{-l} stands for ``locked''. When a file has been checked out
|
||
locked, you are given write permission.
|
||
RCS may say @samp{File locked by somebody}, in which case one must
|
||
negotiate with that person because they have the file locked.
|
||
|
||
There are many ways to specify which revision of a file to check out
|
||
(either locked or unlocked). You can specify a specific revision number,
|
||
symbolic name, date, state or author.
|
||
|
||
@table @samp
|
||
|
||
@item revision
|
||
One explicitly indicates the exact revision desired. Read about
|
||
@code{rlog} to help you select which revision you want.
|
||
@example
|
||
co -r1.3 test.c
|
||
@end example
|
||
retrieves revision 1.3 of the file @file{test.c}. If multiple files are
|
||
specified,
|
||
@example
|
||
co -r1.3 test1.c test2.c test3.c
|
||
@end example
|
||
then RCS would retrieve revision 1.3 of each of the files, probably not
|
||
what is wanted.
|
||
|
||
@item symbolic name
|
||
Use the symbolic name instead of the explicit revision number.
|
||
@example
|
||
co -rVersion_1 test.c
|
||
@end example
|
||
Use of symbolic names is especially useful for a group of files.
|
||
@example
|
||
co -rVersion_1 test1.c test2.c test3.c
|
||
@end example
|
||
gets the appropriate revision of the three files needed to create
|
||
Version_1.
|
||
|
||
@item date
|
||
You can use the @samp{-d} flag to specify a date. The retrieved revision
|
||
is the most recent revision of the file older then the given date.
|
||
@code{co} is very smart about determining what time you actually meant.
|
||
The following forms are all understood:
|
||
@example
|
||
co -d"22-April-1982, 17:20-PDT" test.c
|
||
co -d"2:25 AM, Dec. 29, 1983" test.c
|
||
co -d"Tue-PDT, 1981, 4pm Jul 21" test.c
|
||
@end example
|
||
Note the use of quotes to keep the date as one argument.
|
||
If a time is not completely specified, then default values are assigned.
|
||
|
||
@item state
|
||
It is possible to assign a word that indicates the state of each revision.
|
||
By default, this is @code{Exp} for experimental. The other common state
|
||
is @code{Rel} for released. If you specify a state, such as:
|
||
@example
|
||
co -sRel test.c
|
||
@end example
|
||
then RCS finds the most recent revision with state @code{Rel} and checks
|
||
it out. If you had the following revisions, each with the given state
|
||
then RCS would check out revision 1.11, skipping revisions 1.12 and 2.0.
|
||
@table @var
|
||
@item Revision
|
||
State
|
||
@item 1.10
|
||
Rel
|
||
@item 1.11
|
||
Rel
|
||
@item 1.12
|
||
Exp
|
||
@item 2.0
|
||
Exp
|
||
@end table
|
||
|
||
@item author
|
||
Retrieves the latest revision which was checked in by the user with the
|
||
given login name.
|
||
@example
|
||
co -wpete test.c
|
||
@end example
|
||
gets the latest revision by @code{pete}. Whereas
|
||
@example
|
||
co -w test.c
|
||
@end example
|
||
gets the latest revision checked in by you.
|
||
@end table
|
||
|
||
All of these options can be combined. The first revision that matches
|
||
all the requirements is checked out. If there are no revisions that
|
||
match, then nothing is checked out and an error message is printed.
|
||
The @code{-l} option can also be used with the above to check out the
|
||
selected revision with a lock. Usually, only the @code{-r} option is
|
||
used, the others involving author, date, state are marginally useful.
|
||
|
||
To take a quick look at a revision, the @code{-p} for @samp{print}
|
||
option specifies the file be sent to the screen. This is useful if you
|
||
want a quick look at an old revision of the file, but don't want to
|
||
overwrite the existing version. All the above flags except @code{-l}
|
||
are available.
|
||
|
||
@subsection Keyword Substition
|
||
|
||
Frequently it is useful to maintain some information in a source file
|
||
such as who recently made a change and when that change occurred. A
|
||
further refinement is to arrange for this information to be compiled into
|
||
the code. This is used to determine exactly which versions of a file
|
||
went into making an executable if there are bugs in the executable.
|
||
|
||
RCS will automatically add text into your source when certain
|
||
keywords present. Keywords are of the form @code{$Keyword:$} where everything
|
||
between the @code{:} and @code{$} is replaced with the RCS values.
|
||
|
||
Keywords and their values are:
|
||
|
||
@table @code
|
||
@item $Author:$
|
||
The login name of the user who checked in the revision.
|
||
@item $Date:$
|
||
Date and time the revision was checked in.
|
||
@item $Header:$
|
||
A standard header containing the RCS file name, the revision number,
|
||
date, author and state. This is frequently embedded in a text
|
||
string so that object files can be correctly identified. For example:
|
||
|
||
@example
|
||
#ifndef lint
|
||
static char RCSid[] = "$Header:$";
|
||
#endif
|
||
@end example
|
||
|
||
It is surrounded with the @code{#ifdef lint ... #endif} because lint
|
||
would complain about an unused variable @code{RCSid} and about
|
||
@code{RCSid} being multiply defined. The variable is static so it will
|
||
be unique to this object file and not available to any others. Upon
|
||
being expanded it looks like:
|
||
@example
|
||
static char RCSid[] =
|
||
"$Header: test.c,v 1.2 87/2/4 09:39:07 pete Exp $";
|
||
@end example
|
||
This incorporates all the other information that keywords give except for
|
||
the log message.
|
||
@item $Locker:$
|
||
The login name of the user who locked the revision (empty if not locked).
|
||
@item $Log:$
|
||
The log message supplied during checkin, preceded by a header containing
|
||
the RCS file name, the revision number, the author and the date.
|
||
Existing log messages are not replaced (unlike the other text substituted
|
||
for keywords). Instead, the new log message is inserted after
|
||
@code{$Log:$}. This accumulates a history of all the changes in the
|
||
source file.
|
||
@item $Revision:$
|
||
The revision number assigned to the revision.
|
||
@item $Source:$
|
||
The full pathname of the RCS file.
|
||
@item $State:$
|
||
The state assigned to the revision with @code{rcs -s} or @code{ci -s}
|
||
@end table
|
||
The following example includes all the above:
|
||
@example
|
||
/*
|
||
* $Author: pete $
|
||
* $Date: 87/04/02 14:14:52 $
|
||
* $Header: test.c,v 1.2 87/04/02 14:14:52 pete Locked $
|
||
* $Locker: pete $
|
||
* $Log: test.c,v $
|
||
* Revision 1.2 87/04/02 14:14:52 pete
|
||
* Misspelt Revision keyword.
|
||
*
|
||
* Revision 1.1 87/04/02 14:13:27 pete
|
||
* Initial revision
|
||
*
|
||
* $Revision: 1.2 $
|
||
* $Source: /u0/pete/src/doc/RCS/test.c,v $
|
||
* $State: Exp $
|
||
*/
|
||
|
||
@end example
|
||
The above are placed in a comment block, because that is the typical
|
||
usage. The keywords substitutions occur wherever a keyword is located
|
||
in the file. This keyword substition occurs at check out time, not at
|
||
check in time.
|
||
|
||
@section Check in
|
||
To be able to check in a file, you must first have checked it out locked or
|
||
it must be the initial (first time) check in. When you check a file in,
|
||
you are prompted for a log message which should be one or two lines long
|
||
(although it depends on how many changes you've made). The intention of
|
||
the log messages is to remind yourself and inform others what the
|
||
significant differences are between this revision and the previous
|
||
revision. You terminate the log message with a @code{@.} as the only
|
||
character on a line or by entering @code{^D} (EOF).
|
||
|
||
If the file has never been checked into RCS, you are prompted for an
|
||
initial message which should be some descriptive text describing what the
|
||
file is for. This has limited usefullness since the text cannot be
|
||
included in the source file, and the source file should already be
|
||
documented. In other words, it is acceptable to leave this empty. You
|
||
terminate the initial message the same way as the log message: with a
|
||
@code{@.} on a line by itself or by entering @code{^D} (EOF).
|
||
|
||
If you intend to edit the file immediatly after checking it in, use the
|
||
@code{-l} flag (@b{l}ock), which checks the file out with a lock immediatly
|
||
after checking it in. If you want the file to stick around in the current
|
||
directory, use the @code{-u} flag (@b{u}nlock) to have it checked out
|
||
without a lock immediatly after the check in.
|
||
|
||
If you are checking in a group of files and want the same log message for
|
||
each file, try:
|
||
@example
|
||
ci -m"Renamed variable v to velocity." test1.c test2. test3.c
|
||
@end example
|
||
and RCS will use the @samp{Renamed ... velocity.} for the log message
|
||
for all the files.
|
||
|
||
If you want to give a symbolic name to this revision, now is the best
|
||
time to do so.
|
||
@example
|
||
ci -NVersion_1 test1.c test2.c test3.c
|
||
@end example
|
||
You are limited to alphanumeric characters, @kbd{-}, and @kbd{_}. Each
|
||
of the above files then has Version_1 as the name for the revision. This
|
||
is used in configuration management to allow multiple versions of
|
||
software to exist. You can also use this in a similar manner to maintain
|
||
multiple versions of your programs. RCS enforces the restriction that a
|
||
single name can refer to only one revision. A single revision can be
|
||
known by more than one name. You can use the @code{rcs} command,
|
||
described later, to assing symbolic names after the fact.
|
||
|
||
The state of the revision is assigned at this point. By default it is
|
||
set to @code{Exp} for experimental. To change the default value, you
|
||
must use the @code{-s} flag.
|
||
@example
|
||
ci -sReleased test1.c
|
||
@end example
|
||
|
||
You can also give the revision number when you check in a file. Usually
|
||
you just use RCS's default rules. Occasionally you want to increment the
|
||
main branch number, say from 1.23 to 2.0, then you would type in:
|
||
@example
|
||
ci -r2.0 test1.c
|
||
@end example
|
||
and the new revison would be 2.0. The specified revision number must be
|
||
greater than any other revision number. In the above case, you could not
|
||
check it in as @code{-r1.13} even if there was no revision 1.13.
|
||
|
||
Sooner or later, you are going to attempt to check in a file that you have
|
||
not locked. Theoretically, this should never happen, since you should
|
||
always do a @code{co -l} before editing a file.
|
||
|
||
You need to find out if the file is already locked by somebody else or is
|
||
not locked at all. If it is locked by someone, there are two choices: if
|
||
you have added changes on top of the other persons and your changes are
|
||
much smaller then the other persons, then let the other person check the
|
||
file in; if the other person's changes are less than your changes, then
|
||
have the other person do a @code{rcs -u filename} to unlock the RCS file
|
||
and then you do a @code{rcs -l filename} to lock the file. You can then
|
||
check the file in with @code{ci}.
|
||
|
||
If the file is not locked, then simply do a @code{rcs -l filename} to
|
||
lock the file and then check it in using @code{ci}. However, be careful
|
||
somebody else has not added a revision between the time you got your
|
||
version of the file and the time you check it in. You can use the
|
||
@code{rlog} command to see anything anybody else has done or you can use
|
||
@code{rcsdiff} to compare the your revision of the file with the current
|
||
RCS revision.
|
||
|
||
@chapter Other RCS commands
|
||
|
||
@code{Ci} and @code{co} are the most commonly used commands. There are
|
||
some auxillary commands that are quite useful. You can change the actual
|
||
RCS file with @code{rcs}, compare to revisions of a file with
|
||
@code{rcsdiff}, examine the history of the file with @code{rlog}, combine
|
||
two divergent revisions with @code{rcsmerge}, and find identifying RCS
|
||
keywords in binary or text files.
|
||
|
||
@section Changing attributes
|
||
|
||
Each RCS file has certain characteristics that RCS uses. Some of these
|
||
can be changed during check in time and some it is not conveniant to do
|
||
so at check in time. The command @code{rcs} can be considered a utility
|
||
to operate on RCS files.
|
||
|
||
@subsection Locking and unlocking
|
||
|
||
The most important attribute is whether a file is locked or unlocked. This
|
||
attribute can be changed by saying @code{rcs -l filenames} to lock
|
||
@file{filenames} or @code{rcs -u filenames} to unlock the files. This only
|
||
changes the RCS file (@file{RCS/test.c,v} for example) and not the actual
|
||
file (@file{test.c}). You cannot unlock or lock a file that somebody else
|
||
already has a lock on. Undisciplined use of this command can wreak havoc.
|
||
|
||
@subsection Access list
|
||
|
||
The access list is used to determine who is allowed to lock an RCS file.
|
||
This feature can be used to limit who has the priviledge to modify a file.
|
||
By default it is empty which implies everybody can check the file out
|
||
locked. There are three commands to change the access list:
|
||
@table @code
|
||
@item -a
|
||
Append the following list of login names to the access list.
|
||
@example
|
||
rcs -apete,jim,alex test1.c test2.c test3.c
|
||
@end example
|
||
causes pete, jim, and alex to be added to the list of people allowed to
|
||
check the files @file{test1.c, test2.c}, and @file{test3.c} with a lock.
|
||
If the list was empty, then those three people are the only ones that can
|
||
check it out locked. Note there are no spaces between the names and the
|
||
@code{-a} flag.
|
||
|
||
@item -A
|
||
The argument indicates a RCS filename to find the access list.
|
||
@example
|
||
rcs -Atest1.c test2.c test3.c
|
||
@end example
|
||
adds the access list for file @file{test1.c} to files @file{test2.c}
|
||
and @file{test3.c}.
|
||
|
||
@item -e
|
||
Use the to erase the login names from the access list. This is the
|
||
converse of the @code{-a} option.
|
||
@end table
|
||
|
||
@subsection Symbolic names
|
||
|
||
If you did not assign a symbolic name at check in time, it can be done
|
||
later with @code{rcs}. You can add a name to the current revision, add a
|
||
name to a specified revision, or delete a name.
|
||
|
||
@table @code
|
||
@item -n@i{name}:rev
|
||
Assigns @i{name} to revision @code{rev}. The @kbd{:} acts as a seperator
|
||
between the name and the revision number. It is an error for @i{name} to
|
||
already be assigned a revision, use the @code{-N} option to change a
|
||
revision a name refers to.
|
||
@example
|
||
rcs -nVersion_1:1.13 test.c
|
||
@end example
|
||
|
||
If you do not specify a revision, then @i{name} is deleted.
|
||
@example
|
||
rcs -nVersion_1 test.c
|
||
@end example
|
||
deletes the symbolic name @i{Version_1}.
|
||
|
||
@item -N@i{name}:rev
|
||
Identical to @code{-n} except if the symbolic name @i{name} exists, it is
|
||
reassigned to the specified revision @code{rev}.
|
||
|
||
@item -S@i{name}
|
||
Useful if you want to do large scale assignment of a symbolic name to
|
||
the current revision (on the trunk). Works like @code{-n}, including not
|
||
allowing overriding a previous assignment of @i{name}.
|
||
|
||
@end table
|
||
|
||
@subsection Comment string
|
||
|
||
The comment string (or comment leader) is printed before every line add
|
||
from the expansion of the @code{$Log$} keyword. When an RCS file is
|
||
initialy checked in, RCS guesses at what this string should be based on the
|
||
suffix of the file name. For example, it is set to ``@code{ * }'' for files
|
||
ending in @file{.c} and to ``@code{c }'' for files ending in @file{.f}. It
|
||
can be changed to any string.
|
||
@example
|
||
rcs -c"### " test.c
|
||
@end example
|
||
Note the use of quotes to get the space as part of the comment string.
|
||
|
||
@subsection Strict locking
|
||
|
||
Strict locking is the default. It means the owner of a file cannot check
|
||
a file in without having first locked the file. Struct locking is set
|
||
with the @code{-L} flag. Non-strict locking means
|
||
the owner of the file can just check the file in. It is set with the
|
||
@code{-U} flag. There is no reason to use this. Keep locking as strict
|
||
(@code{-L}) which is the default.
|
||
|
||
@subsection State
|
||
|
||
You can change the state of any revision of the file.
|
||
@example
|
||
rcs -sReleased RCS/*,v
|
||
@end example
|
||
sets the state to @code{Released} for the current revision of each file
|
||
in the RCS directory. To set the state for a specific revision:
|
||
@example
|
||
rcs -sReleased:1.10 test.c
|
||
@end example
|
||
or
|
||
@example
|
||
rcs -r1.10 -sReleased test.c
|
||
@end example
|
||
are equivalent.
|
||
|
||
@subsection Descriptive text
|
||
The descriptive text has limited usefulness. When you first check a file
|
||
into RCS, you are prompted for the descriptive text. To change that text,
|
||
use the @code{-t} option to @code{rcs}. The following example enters
|
||
one line of descriptive text:
|
||
@example
|
||
demo% rcs -t test.c
|
||
RCS file: RCS/test.c,v
|
||
enter description, terminated with ^D or '.':
|
||
NOTE: This is NOT the log message!
|
||
>> A simple test file.
|
||
>> .
|
||
done
|
||
@end example
|
||
You can also specify a file to be used as the descriptive text. This is
|
||
useful if you want the descriptive text to be the same for a group of
|
||
files
|
||
@example
|
||
rcs -t/tmp/message *.c *.h Makefile
|
||
@end example
|
||
uses the text in @file{/tmp/message} as the descriptive text for all the
|
||
@code{C}, include, and make files.
|
||
|
||
@subsection Deleting revisions
|
||
|
||
Occasionally, you may decide that an RCS file is taking up too much disk
|
||
space and it is time to clean things up or you could just be embarrased
|
||
by a particular revision and want to get rid of it. You can delete a
|
||
range of revisions. Symbolic names can be used to specify the range.
|
||
(The @code{-o} stands for ``outdates'').
|
||
|
||
@example
|
||
rcs -o1.4 test.c
|
||
@end example
|
||
deletes revision @code{1.4}.
|
||
@example
|
||
rcs -o1.4-1.10 test.c
|
||
@end example
|
||
deletes everything between revisions 1.4 and 1.10. The following is a
|
||
little more daring (and foolish):
|
||
@example
|
||
rcs -oVersion_1-Version_2 test.c
|
||
@end example
|
||
deletes all the intermediate files between Version_1 and Version_2 (the
|
||
daring part).
|
||
However it also deletes Version_1 and Version_2 (the foolish part) since
|
||
the range is inclusive.
|
||
@example
|
||
rcs -o-1.4 test.c
|
||
@end example
|
||
deletes everything up to and includeing revision 1.4 (this is probably
|
||
equivalent to 1.1-1.4).
|
||
@example
|
||
rcs -o1.4- test.c
|
||
@end example
|
||
deletes everything after revision 1.4, inclusive.
|
||
|
||
None of the outdated revisions may have branches or locks.
|
||
|
||
@section Printing differences
|
||
|
||
You can find out all the changes from one revision to the next or between
|
||
any pair of revisions with the @code{rcsdiff} command. @code{rcsdiff}
|
||
accepts the same options as @code{diff}.
|
||
|
||
You can diff the current, working version (the file that is in your
|
||
directory) with any previous revision of the file. If you do not
|
||
explicitly indicate which revision, @code{rcsdiff} uses the latest
|
||
revision on the trunk.
|
||
@example
|
||
rcsdiff test.c
|
||
@end example
|
||
compares the working version of @file{test.c} with the file you would get
|
||
if you said @code{co test.c}.
|
||
|
||
If you specify only one revision, then @code{rcsdiff} retrieves that
|
||
revision and compares it with the working version.
|
||
@example
|
||
rcsdiff -rVersion_1 test.c
|
||
@end example
|
||
Uses the symbolic name @i{Version_1} to compare against.
|
||
|
||
If you specify two revisions, then those two revisions of the file are
|
||
compared and the working file is ignored.
|
||
@example
|
||
rcsdiff -rVersion_1 -rVersion_2 test.c
|
||
@end example
|
||
finds the differences between the two versions, ignoring what
|
||
@file{test.c} might look like.
|
||
|
||
Multiple file names may be given, in which case the comparison is
|
||
performed for each file.
|
||
@example
|
||
rcsdiff -rVersion_1 -rVersion_2 RCS/*,v
|
||
@end example
|
||
prints the changes between the two versions for each file.
|
||
|
||
@section Log messages
|
||
|
||
To find out the state of an RCS file or to look at the revision history
|
||
of the file, use the @code{rlog} command. If no options are specified
|
||
you get a header that tells you the current state of the file followed by
|
||
log message for each revision.
|
||
@example
|
||
demo% rlog test.c
|
||
|
||
RCS file: RCS/test.c,v; Working file: test.c
|
||
head: 1.3
|
||
locks: ; strict
|
||
access list:
|
||
symbolic names: V3: 1.3; V1: 1.1;
|
||
comment leader: " * "
|
||
total revisions: 3; selected revisions: 3
|
||
description:
|
||
A simple test file.
|
||
----------------------------
|
||
revision 1.3
|
||
date: 87/04/07 11:50:58; author: pete; state: Exp;
|
||
lines added/del: 6/3
|
||
fjsadl.
|
||
----------------------------
|
||
revision 1.2
|
||
date: 87/04/02 14:14:52; author: pete; state: Exp;
|
||
lines added/del: 11/8
|
||
Misspelt Revision keyword.
|
||
----------------------------
|
||
revision 1.1
|
||
date: 87/04/02 14:13:27; author: pete; state: Exp;
|
||
Initial revision
|
||
=======================================================
|
||
demo%
|
||
@end example
|
||
|
||
@section Merging versions
|
||
|
||
@code{rcsmerge}
|
||
|
||
@section Identifying files
|
||
|
||
@code{ident}
|
||
|
||
@chapter RCS Problems
|
||
|
||
Occasionally something will go wrong with RCS, t is designed so you are
|
||
safe from losing a file, however. Most problems result from not having
|
||
locked a file or from working on a file that somebody else has locked.
|
||
If this happens, you should see the section on ``Changing attributes.''
|
||
|
||
It is safe to interrupt (use ^C) an RCS operation. It prints a message
|
||
about RCS cleaning up and restores the file it was working on.
|
||
Occasionally, though, some catastrophe such as the file system filling up
|
||
or a file server going down is handled less than gracefully. When this
|
||
happens, you should use @code{rlog} to see what state the file was left
|
||
in. It may still need to be checked in or out. Liberal use of
|
||
@code{rcsdiff} to compare the working version of the file with the RCS
|
||
version may verify which version you want checked in.
|
||
|
||
Occasionally, you'll get the message:
|
||
@example
|
||
demo% co test.c
|
||
co error: RCS file RCS/test.c,v is in use
|
||
demo%
|
||
@end example
|
||
this means either somebody else is using RCS to access @file{test.c}
|
||
in which case you should be able to try again in a few seconds or a
|
||
catastrophe (see above) has occurred and RCS left a semaphore file
|
||
around. The name of the semaphore file will be @file{RCS/,filename,}
|
||
where the @code{,} is prepended and appended to the name of the working
|
||
file. If this file exists and is more than a few seconds old, it can be
|
||
safely removed.
|
||
|
||
If you have locked a file and not made any changes, but attempt to check
|
||
it back in but using the @code{-u} flag to have it checked out unlocked
|
||
immediatly after, the file will not be unlocked. The following
|
||
illustrates this.
|
||
@example
|
||
demo% co -l test.c
|
||
RCS/test.c,v --> test.c
|
||
revision 1.3 (locked)
|
||
done
|
||
demo% ci -u test.c
|
||
RCS/test.c,v <-- test.c
|
||
new revision: 1.4; previous revision: 1.3
|
||
File test.c is unchanged with respect to revision 1.3
|
||
checkin anyway? [ny](n): n
|
||
checkin aborted; test.c not deleted.
|
||
demo% rlog -h test.c
|
||
|
||
RCS file: RCS/test.c,v; Working file: test.c
|
||
head: 1.3
|
||
locks: pete: 1.3; strict
|
||
access list:
|
||
symbolic names: V3: 1.3; V1: 1.1;
|
||
comment leader: " * "
|
||
total revisions: 3;
|
||
========================================================
|
||
demo%
|
||
@end example
|
||
Notice that the state is still locked. The best thing to do in this case
|
||
is to unlock the file using the @code{rcs} command an then to check it
|
||
out unlocked.
|
||
@example
|
||
demo% rcs -u test.c
|
||
RCS file: RCS/test.c,v
|
||
1.3 unlocked
|
||
done
|
||
demo% co test.c
|
||
RCS/test.c,v --> test.c
|
||
revision 1.3
|
||
writable test.c exists; overwrite? [ny](n): y
|
||
done
|
||
@end example
|
||
|
||
|
||
@chapter Using RCS for multiple versions
|
||
|
||
Maintaining multiple versions of software is difficult. Usually there are
|
||
two versions (at least) -- a working version and a version under
|
||
development. It is impossible to maintain the two versions in the same
|
||
directory since everytime a file was compiled for one version or the other,
|
||
it would clobber the file that was there previously. So a seperate
|
||
directory structure is maintained -- one that contains the working
|
||
version and the other the version that is under development. So now the
|
||
question becomes, ``How to copy the source from on place to the next?''
|
||
|
||
You could ``release'' the source file to someone, who takes
|
||
responsibility for copying it to the appropriate area. This works to a
|
||
limited degree. As more people release files, the person doing the
|
||
copying is more likely to miss files or copy the wrong ones. It is also
|
||
difficult to continue development on a module if you are not sure exactly
|
||
when the person doing the copying will copy it.
|
||
|
||
The simplest method is to just let RCS take care of it. One uses
|
||
symbolic links to the RCS directory to get access to the RCS files. This
|
||
keeps the files seperate and allows RCS to control access to the files,
|
||
which is what it is designed to do. All the RCS commands will work if
|
||
the RCS directory is accessed through a symbolic link. The following
|
||
commands will make a miniature directory structure that should illustrate
|
||
the method.
|
||
|
||
@example
|
||
mkdir v1 v2 # version 1 and 2
|
||
mkdir v1/src v1/include v2/src v2/include # main directories
|
||
mkdir v1/src/RCS v1/include/RCS # directories for RCS
|
||
|
||
# Now create the symbolic links to the RCS directories
|
||
cd v2/src
|
||
ln -s ../../v1/src/RCS v2/src/RCS
|
||
cd ../include
|
||
ln -s ../../v1/include/RCS v2/src/RCS
|
||
@end example
|
||
|
||
If there were some files in the RCS directories under @file{v1/src}, then
|
||
they could be checked out under both @file{v1/src} and @file{v2/src} (of
|
||
course only one could be locked). The revision's checked are independent.
|
||
The revision under @file{v1} could be 1.4 and under @file{v2} it could be
|
||
revision 1.23 that is checked out. Two people could be compiling different
|
||
versions of the software without clobbering each others work.
|
||
|
||
This is great, except one does not want to have to keep track of the
|
||
appropriate revision number for each file in the system. This is where
|
||
RCS's symbolic names (not symbolic links, which are from Unix) come in.
|
||
To compile a particular version of the software, one specifies that
|
||
revision @i{Ver1} is to be checked out.
|
||
@example
|
||
co -rVer1 test.c
|
||
@end example
|
||
or, if using make:
|
||
@example
|
||
make COFLAGS="-rVer1"
|
||
@end example
|
||
This would compile version 1 of the software (assuming @i{Ver1} meant
|
||
version 1, not version 2).
|
||
|
||
The developer is responsible for assigning the symbolic name, since that
|
||
is the person who knows when a revision is ready for a particular version
|
||
of the software. Assigning symbolic names can be done at check in time
|
||
or with the @code{rcs} command. Assigning a symbolic name to a revision
|
||
should not be done lightly. It implies that file is ready for release
|
||
into this version of the software. Updating a name to refer to a
|
||
different revision should not be done lightly because someday someone
|
||
might want to build that exact version of the software with that exact
|
||
bug that was fixed by your newest version. While this may not be too
|
||
likely, it should be considered.
|
||
|
||
The number of symbolic names is limitless, so there is no need to limit
|
||
yourself to names such as @code{Ver1}. We might use @code{Ver1_1},
|
||
@code{Ver1_2}, @dots{} and so on as needed. At the same time, one might
|
||
want to keep track of your own particular versions. This can be done by
|
||
selecting names that do not conflict (and hopefully will never conflict)
|
||
with names used by the overall system. A name like @code{pete1_1} is
|
||
fairly safe.
|
||
|
||
@chapter Summary
|
||
|
||
The following is a concise listing of commands and options. It assumes
|
||
you already know what a command does and how the options work -- you just
|
||
need to be reminded.
|
||
|
||
@section ci
|
||
|
||
Check a locked file back into RCS.
|
||
@table @code
|
||
@item -u
|
||
after check in, check it out again locked.
|
||
|
||
@item -l
|
||
after check in, check it out again locked.
|
||
|
||
@item -r
|
||
assign the revision the specified revision number.
|
||
|
||
@item -f
|
||
force a deposit even if the two versions are not different.
|
||
|
||
@item -k
|
||
use already existing keyword values for revision information.
|
||
|
||
@item -q
|
||
quiet mode.
|
||
|
||
@item -m
|
||
use the following text as the message.
|
||
|
||
@item -n
|
||
assign a symbolic name to this revision
|
||
|
||
@item -N
|
||
assign a symbolic name to this revision. Overides a previous assignment.
|
||
|
||
@item -s
|
||
assing the given state to this file
|
||
|
||
@item -t
|
||
use the named file for the descriptive text. If a file is omitted, the
|
||
user is prompted for the text.
|
||
|
||
@end table
|
||
|
||
@section co
|
||
|
||
Check a file out from RCS.
|
||
|
||
@table @code
|
||
|
||
@item -l
|
||
locks the checked out revision.
|
||
|
||
@item -p
|
||
prints the retrieved revision on the standard output.
|
||
|
||
@item -q
|
||
quiet mode.
|
||
|
||
@item -d
|
||
check out the newest revision older than date.
|
||
|
||
@item -r
|
||
check out the specified revision
|
||
|
||
@item -s
|
||
check out the latest revision with the specified state.
|
||
|
||
@item -w
|
||
retrieves the latest revision checked in by the user with the given login
|
||
name.
|
||
|
||
@item -j
|
||
generates a new revision which is the join of the given revisions.
|
||
|
||
@end table
|
||
|
||
@section rcs
|
||
|
||
Change RCS file attributes.
|
||
@table @code
|
||
|
||
@item -i
|
||
create and initialize a new RCS file.
|
||
|
||
@item -a
|
||
append the following login names to the access list.
|
||
|
||
@item -A
|
||
append the login names on the access list of the specifed file to the
|
||
file being checked in.
|
||
|
||
@item -e
|
||
erase the login names from the access list.
|
||
|
||
@item -c
|
||
set the comment leader to the given string.
|
||
|
||
@item -l
|
||
locks the revision. (@code{co -l} is preferred)
|
||
|
||
@item -u
|
||
unlocks the specified revision.
|
||
|
||
@item -L
|
||
sets locking to strict (the default).
|
||
|
||
@item -U
|
||
sets locking to non-strict (discouraged).
|
||
|
||
@item -n
|
||
assigns symbolic name to a specified revision
|
||
|
||
@item -N
|
||
assigns symbolic name to a specified revision. Overides previous uses of
|
||
the name.
|
||
|
||
@item -S
|
||
similar to @code{-n} except the most recent revision on the trunk is
|
||
assigned the symbolic name.
|
||
|
||
@item -o
|
||
deletes (``outdates'') the revisions in the give range.
|
||
|
||
@item -q
|
||
quiet mode.
|
||
|
||
@item -s
|
||
sets the state attribute to the specified revision.
|
||
|
||
@item -t
|
||
writes descriptive text into the RCS file.
|
||
|
||
@end table
|
||
|
||
@section rcsdiff
|
||
|
||
Compare revisions of RCS files.
|
||
|
||
@table @code
|
||
|
||
@item -r
|
||
Compare the working version of the file with the specified revision. If
|
||
two @code{-r} flags are given, then the two specified revisions are
|
||
compared.
|
||
|
||
@item -b
|
||
ignore trailing blanks and treat all other strings of blanks as
|
||
equivalent.
|
||
|
||
@item -c
|
||
produce a context diff.
|
||
|
||
@item -e
|
||
produce a script of commands for @code{ed} to recreate the files.
|
||
|
||
@item -f
|
||
similar to @code{-e} except in the opposite order (not useful for
|
||
@code{ed}).
|
||
|
||
@item -h
|
||
does a fast, half-hearted job.
|
||
|
||
@section rcsmerge
|
||
|
||
Merges revisions of a file. Difficult to use.
|
||
|
||
@section rlog
|
||
|
||
Print log messages and other information about RCS files.
|
||
|
||
@table @code
|
||
|
||
@item -L
|
||
ignores RCS files that have no locks set.
|
||
|
||
@item -R
|
||
only prints the name of the RCS file
|
||
|
||
@item -h
|
||
prints only the RCS file name, working file name, head, access list,
|
||
locks, symbolic names and suffix.
|
||
|
||
@item -t
|
||
same as @code{-h}, plus the descriptive text is printed.
|
||
|
||
@item -d
|
||
prints information about revisions within the checkin date/time in the
|
||
ranges given.
|
||
|
||
@item -l
|
||
prints information about locked revisions.
|
||
|
||
@item -r
|
||
prints information about revisions given in the comma seperated list of
|
||
revisions.
|
||
|
||
@item -s
|
||
prints information about revisions whose state attributes match the given
|
||
state.
|
||
|
||
@item -w
|
||
prints information about revisions checked in by users with login names
|
||
appearing in the list.
|
||
|
||
@end table
|
||
@contents
|
||
|
||
@ignore
|
||
Local Variables:
|
||
vi-wrap-flag:t
|
||
End:
|
||
@end ignore
|
||
@bye
|