\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