What RCS does
*************

RCS stands for Revision Control System and is made of seven programs: ci, co, rcs, rcsmerge, rcsdiff, ident, and rlog.  In addition, make knows about RCS and is able to interact with RCS.  Files under RCS management are distuingished by having a ,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 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 must learn two things: to check out a file before changing it and to check the file back in after changes are made.

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

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 lock a file prior to editing it; only one person can have a lock at a time.  The above is called access control.

Since RCS can keep its files in a subdirectory called RCS of your working directory, it is easy to allow multiple references to the source code.  This is done by creating a soft link with the command ln -s to the RCS directory itself.  RCS then thinks this is a normal 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.

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.

RCS and make
============

make knows about RCS and how to get files from it.  If a source file is missing, make looks for the corresponding RCS file and performs a check out.  make also checks if the RCS file is more recent then the current file and attempts to check it out if it is. Everytime 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 (.o's) to maintain the correct relationship.  Also, an object (.o) file will not be recompiled if the RCS version has not changed, even if make had to check it out from RCS to find the file.  When make is finished, it removes any files it had to check out from RCS.

In other words, make may seem to be checking out a lot of files from RCS, but they are not being recompiled.

This is not available at all sites!

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 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:

     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?

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.

Basic RCS commands
******************

There are two commands that are used on a regular basis, ci (``check-in'') and 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.

Definitions
===========

It is time to explicitly define the terminology.  It is straight forward, although somehow confusion arises when actually doing things.

Delta
Revision
     A 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 delta.

Check in
     When you are finished with a set of changes, you check the file back into RCS using the 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.

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.

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

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 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 1.1 or 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 2.3 it would initially be called revision 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.

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.

Soft (symbolic) Links
     Soft links are a method that Unix uses to reference another file or directory.  They are created with the command ln -s orig-file symbolic-name.

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

     co test.c

this retrieves the most recent revision of the file (obtained from 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 chmod u+w file.c, but in that case why not just check it out locked?).

To check out a file with a lock:

     co -l test.c

the -l stands for ``locked''.  When a file has been checked out locked, you are given write permission. RCS may say 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.

revision
     One explicitly indicates the exact revision desired.  Read about rlog to help you select which revision you want.

          co -r1.3 test.c

     retrieves revision 1.3 of the file test.c.  If multiple files are specified,

          co -r1.3 test1.c test2.c test3.c

     then RCS would retrieve revision 1.3 of each of the files, probably not what is wanted.

symbolic name
     Use the symbolic name instead of the explicit revision number.

          co -rVersion_1 test.c

     Use of symbolic names is especially useful for a group of files.

          co -rVersion_1 test1.c test2.c test3.c

     gets the appropriate revision of the three files needed to create Version_1.

date
     You can use the -d flag to specify a date.  The retrieved revision is the most recent revision of the file older then the given date. co is very smart about determining what time you actually meant. The following forms are all understood:

          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

     Note the use of quotes to keep the date as one argument. If a time is not completely specified, then default values are assigned.

state
     It is possible to assign a word that indicates the state of each revision. By default, this is Exp for experimental.  The other common state is Rel for released.  If you specify a state, such as:

          co -sRel test.c

     then RCS finds the most recent revision with state 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.

     Revision
          State

     1.10
          Rel

     1.11
          Rel

     1.12
          Exp

     2.0
          Exp

author
     Retrieves the latest revision which was checked in by the user with the given login name.

          co -wpete test.c

     gets the latest revision by pete.  Whereas

          co -w test.c

     gets the latest revision checked in by you.

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 -l option can also be used with the above to check out the selected revision with a lock.  Usually, only the -r option is used, the others involving author, date, state are marginally useful.

To take a quick look at a revision, the -p for 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 -l are available.

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 $Keyword:$ where everything between the : and $ is replaced with the RCS values.

Keywords and their values are:

$Author:$
     The login name of the user who checked in the revision.

$Date:$
     Date and time the revision was checked in.

$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:

          #ifndef lint
          static char RCSid[] = "$Header:$";
          #endif

     It is surrounded with the #ifdef lint ... #endif because lint would complain about an unused variable RCSid and about 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:

          static char RCSid[] =
          "$Header: test.c,v 1.2 87/2/4 09:39:07 pete Exp $";

     This incorporates all the other information that keywords give except for the log message.

$Locker:$
     The login name of the user who locked the revision (empty if not locked).

$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 $Log:$.  This accumulates a history of all the changes in the source file.

$Revision:$
     The revision number assigned to the revision.

$Source:$
     The full pathname of the RCS file.

$State:$
     The state assigned to the revision with rcs -s or ci -s

The following example includes all the above:

     /*
      * $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 $
      */

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.

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 .  as the only character on a line or by entering ^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 . on a line by itself or by entering ^D (EOF).

If you  intend to edit  the file immediatly  after checking  it in, use the -l flag (lock), 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 -u flag  (unlock)  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:

     ci -m"Renamed variable v to velocity." test1.c test2. test3.c

and RCS will use the 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.

     ci -NVersion_1 test1.c test2.c test3.c

You are limited to alphanumeric characters, -, and _.  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 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 Exp for experimental.  To change the default value, you must use the -s flag.

     ci -sReleased test1.c

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:

     ci -r2.0 test1.c

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 -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 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 rcs -u  filename to unlock the RCS  file and  then you do a rcs  -l filename to lock  the file.  You can then check the file in with ci.

If the file is not locked, then simply do a rcs -l filename to lock the file and then check it in using 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 rlog command to see anything anybody else has done or you can use rcsdiff to compare the your revision of the file with the current RCS revision.

Other RCS commands
******************

Ci and  co are the   most commonly used  commands.  There are
some auxillary commands that are quite useful.   You can change  the actual
RCS   file   with   rcs,  compare  to  revisions  of    a file  with
rcsdiff, examine  the history of  the file with rlog, combine
two divergent revisions   with rcsmerge,  and  find identifying  RCS
keywords in binary or text files.

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 rcs can be considered a utility to operate on RCS files.

Locking and unlocking
---------------------

The most important attribute is whether a file is locked or unlocked.  This attribute can  be  changed  by  saying  rcs   -l filenames  to  lock filenames or rcs -u filenames to unlock the files.  This only changes the RCS file  (RCS/test.c,v for example)  and not the actual 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.

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:

-a
     Append the following list of login names to the access list.

          rcs -apete,jim,alex test1.c test2.c test3.c

     causes pete, jim, and alex to be added to the list of people allowed to check the files test1.c, test2.c, and 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 -a flag.

-A
     The argument indicates a RCS filename to find the access list.

          rcs -Atest1.c test2.c test3.c

     adds the access list for file test1.c to files test2.c and test3.c.

-e
     Use the to erase the login names from the access list.  This is the converse of the -a option.

Symbolic names
--------------

If you did not assign a symbolic name at check in time, it can be done later with rcs.  You can add a name to the current revision, add a name to a specified revision, or delete a name.

-nname:rev
     Assigns name to revision rev.  The : acts as a seperator between the name and the revision number.  It is an error for name to already be assigned a revision, use the -N option to change a revision a name refers to.

          rcs -nVersion_1:1.13 test.c

     If you do not specify a revision, then name is deleted.

          rcs -nVersion_1 test.c

     deletes the symbolic name Version_1.

-Nname:rev
     Identical to -n except if the symbolic name name exists, it is reassigned to the specified revision rev.

-Sname
     Useful if  you want to do large scale assignment of a symbolic name to the current revision (on the trunk).  Works like -n, including not allowing overriding a previous assignment of name.

Comment string
--------------

The comment string  (or comment leader)  is printed before  every line  add from the expansion  of  the $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 `` * '' for files ending in .c and to ``c '' for files ending in .f.  It can be changed to any string.

     rcs -c"### " test.c

Note the use of quotes to get the space as part of the comment string.

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 -L flag.  Non-strict locking means the owner of the file can just check the file in.  It is set with the -U flag.  There is no reason to use this.  Keep locking as strict (-L) which is the default.

State
-----

You can change the state of any revision of the file.

     rcs -sReleased RCS/*,v

sets the state to Released for the current revision of each file in the RCS directory.  To set the state for a specific revision:

     rcs -sReleased:1.10 test.c

or

     rcs -r1.10 -sReleased test.c

are equivalent.

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 -t option to rcs.  The following example enters one line of descriptive text:

     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

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

     rcs -t/tmp/message *.c *.h Makefile

uses the text in /tmp/message as the descriptive text for all the C, include, and make files.

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 -o stands for ``outdates'').

     rcs -o1.4 test.c

deletes revision 1.4.

     rcs -o1.4-1.10 test.c

deletes everything between revisions 1.4 and 1.10.  The following is a little more daring (and foolish):

     rcs -oVersion_1-Version_2 test.c

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.

     rcs -o-1.4 test.c

deletes everything up to and includeing revision 1.4 (this is probably equivalent to 1.1-1.4).

     rcs -o1.4- test.c

deletes everything after revision 1.4, inclusive.

None of the outdated revisions may have branches or locks.

Printing differences
====================

You can find out all the changes from one revision to the next or between any pair of revisions with the rcsdiff command.  rcsdiff accepts the same options as 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, rcsdiff uses the latest revision on the trunk.

     rcsdiff test.c

compares the working version of test.c with the file you would get if you said co test.c.

If you specify only one revision, then rcsdiff retrieves that revision and compares it with the working version.

     rcsdiff -rVersion_1 test.c

Uses the symbolic name 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.

     rcsdiff -rVersion_1 -rVersion_2 test.c

finds the differences between the two versions, ignoring what test.c might look like.

Multiple file names may be given, in which case the comparison is performed for each file.

     rcsdiff -rVersion_1 -rVersion_2 RCS/*,v

prints the changes between the two versions for each file.

Log messages
============

To find out the state of an RCS file or to look at the revision history of the file, use the 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.

     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%

Merging versions
================

rcsmerge

Identifying files
=================

ident

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 rlog to see what state the file was left in.  It may still need to be checked in or out.  Liberal use of 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:

     demo% co test.c
     co error: RCS file RCS/test.c,v is in use
     demo%

this means either somebody else is using RCS to access 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 RCS/,filename, where the , 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 -u flag to have it checked out unlocked immediatly after, the file will not be unlocked.  The following illustrates this.

     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%

Notice that the state is still locked.  The best thing to do in this case is to unlock the file using the rcs command an then to check it out unlocked.

     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

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.

     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

If there were some files in the RCS  directories under  v1/src, then they could be checked  out under both  v1/src and  v2/src (of course only one could be locked).  The  revision's checked are independent. The revision under v1 could be 1.4 and  under 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 Ver1 is to be checked out.

     co -rVer1 test.c

or, if using make:

     make COFLAGS="-rVer1"

This would compile version 1 of the software (assuming 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 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 Ver1.  We might use Ver1_1, Ver1_2, ... 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 no conflict (and hopefully will never conflict) with names used by the overall system.  A name like pete1_1 is fairly safe.

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.

ci
==

Check a locked file back into RCS.

-u
     after check in, check it out again locked.

-l
     after check in, check it out again locked.

-r
     assign the revision the specified revision number.

-f
     force a deposit even if the two versions are not different.

-k
     use already existing keyword values for revision information.

-q
     quiet mode.

-m
     use the following text as the message.

-n
     assign a symbolic name to this revision

-N
     assign a symbolic name to this revision.   Overides a previous assignment.

-s
     assing the given state to this file

-t
     use the named file for the descriptive text.  If a file is omitted, the user is prompted for the text.

co
==

Check a file out from RCS.

-l
     locks the checked out revision.

-p
     prints the retrieved revision on the standard output.

-q
     quiet mode.

-d
     check out the newest revision older than date.

-r
     check out the specified revision

-s
     check out the latest revision with the specified state.

-w
     retrieves the latest revision checked in by the user with the given login name.

-j
     generates a new revision which is the join of the given revisions.

rcs
===

Change RCS file attributes.

-i
     create and initialize a new RCS file.

-a
     append the following login names to the access list.

-A
     append the login names on the access list of the specifed file to the file being checked in.

-e
     erase the login names from the access list.

-c
     set the comment leader to the given string.

-l
     locks the revision.  (co -l is preferred)

-u
     unlocks the specified revision.

-L
     sets locking to strict (the default).

-U
     sets locking to non-strict (discouraged).

-n
     assigns symbolic name to a specified revision

-N
     assigns symbolic name to a specified revision.  Overides previous uses of the name.

-S
     similar to -n except the most recent revision on the trunk is assigned the symbolic name.

-o
     deletes (``outdates'') the revisions in the give range.

-q
     quiet mode.

-s
     sets the state attribute to the specified revision.

-t
     writes descriptive text into the RCS file.

rcsdiff
=======

Compare revisions of RCS files.

-r
     Compare the working version of the file with the specified revision.  If two -r flags are given, then the two specified revisions are compared.

-b
     ignore trailing blanks and treat all other strings of blanks as equivalent.

-c
     produce a context diff.

-e
     produce a script of commands for ed to recreate the files.

-f
     similar to -e except in the opposite order (not useful for ed).

-h
     does a fast, half-hearted job.

rcsmerge
========

Merges revisions of a file.  Difficult to use.

rlog
====

Print log messages and other information about RCS files.

-L
     ignores RCS files that have no locks set.

-R
     only prints the name of the RCS file

-h
     prints only the RCS file name, working file name, head, access list, locks, symbolic names and suffix.

-t
     same as -h, plus the descriptive text is printed.

-d
     prints information about revisions within the checkin date/time in the ranges given.

-l
     prints information about locked revisions.

-r
     prints information about revisions given in the comma seperated list of revisions.

-s
     prints information about revisions whose state attributes match the given state.

-w
     prints information about revisions checked in by users with login names appearing in the list.