This is Info file cvs.info, produced by Makeinfo-1.63 from the input file ./cvs.texinfo. Copyright (C) 1992, 1993 Signum Support AB Copyright (C) 1993, 1994 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the section entitled "GNU General Public License" is included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the section entitled "GNU General Public License" and this permission notice may be included in translations approved by the Free Software Foundation instead of in the original English.  File: cvs.info, Node: File status, Next: Updating a file, Up: Multiple developers File status =========== After you have checked out a file out from CVS, it is in one of these four states: Up-to-date The file is identical with the latest revision in the repository. Locally modified You have edited the file, and not yet committed your changes. Needing update Someone else has committed a newer revision to the repository. Needing merge Someone else have committed a newer revision to the repository, and you have also made modifications to the file. You can use the `status' command to find out the status of a given file. *Note status::.  File: cvs.info, Node: Updating a file, Next: Conflicts example, Prev: File status, Up: Multiple developers Bringing a file up to date ========================== When you want to update or merge a file, use the `update' command. For files that are not up to date this is roughly equivalent to a `checkout' command: the newest revision of the file is extracted from the repository and put in your working copy of the module. Your modifications to a file are never lost when you use `update'. If no newer revision exists, running `update' has no effect. If you have edited the file, and a newer revision is available, CVS will merge all changes into your working copy. For instance, imagine that you checked out revision 1.4 and started editing it. In the meantime someone else committed revision 1.5, and shortly after that revision 1.6. If you run `update' on the file now, CVS will incorporate all changes between revision 1.4 and 1.6 into your file. If any of the changes between 1.4 and 1.6 were made too close to any of the changes you have made, an "overlap" occurs. In such cases a warning is printed, and the resulting file includes both versions of the lines that overlap, delimited by special markers. *Note update::, for a complete description of the `update' command.  File: cvs.info, Node: Conflicts example, Next: Informing others, Prev: Updating a file, Up: Multiple developers Conflicts example ================= Suppose revision 1.4 of `driver.c' contains this: #include void main() { parse(); if (nerr == 0) gencode(); else fprintf(stderr, "No code generated.\n"); exit(nerr == 0 ? 0 : 1); } Revision 1.6 of `driver.c' contains this: #include int main(int argc, char **argv) { parse(); if (argc != 1) { fprintf(stderr, "tc: No args expected.\n"); exit(1); } if (nerr == 0) gencode(); else fprintf(stderr, "No code generated.\n"); exit(!!nerr); } Your working copy of `driver.c', based on revision 1.4, contains this before you run `cvs update': #include #include void main() { init_scanner(); parse(); if (nerr == 0) gencode(); else fprintf(stderr, "No code generated.\n"); exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } You run `cvs update': $ cvs update driver.c RCS file: /usr/local/cvsroot/yoyodyne/tc/driver.c,v retrieving revision 1.4 retrieving revision 1.6 Merging differences between 1.4 and 1.6 into driver.c rcsmerge warning: overlaps during merge cvs update: conflicts found in driver.c C driver.c CVS tells you that there were some conflicts. Your original working file is saved unmodified in `.#driver.c.1.4'. The new version of `driver.c' contains this: #include #include int main(int argc, char **argv) { init_scanner(); parse(); if (argc != 1) { fprintf(stderr, "tc: No args expected.\n"); exit(1); } if (nerr == 0) gencode(); else fprintf(stderr, "No code generated.\n"); <<<<<<< driver.c exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE); ======= exit(!!nerr); >>>>>>> 1.6 } Note how all non-overlapping modifications are incorporated in your working copy, and that the overlapping section is clearly marked with `<<<<<<<', `=======' and `>>>>>>>'. You resolve the conflict by editing the file, removing the markers and the erroneous line. Suppose you end up with this file: #include #include int main(int argc, char **argv) { init_scanner(); parse(); if (argc != 1) { fprintf(stderr, "tc: No args expected.\n"); exit(1); } if (nerr == 0) gencode(); else fprintf(stderr, "No code generated.\n"); exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } You can now go ahead and commit this as revision 1.7. $ cvs commit -m "Initialize scanner. Use symbolic exit values." driver.c Checking in driver.c; /usr/local/cvsroot/yoyodyne/tc/driver.c,v <-- driver.c new revision: 1.7; previous revision: 1.6 done If you use release 1.04 or later of pcl-cvs (a GNU Emacs front-end for CVS) you can use an Emacs package called emerge to help you resolve conflicts. See the documentation for pcl-cvs.  File: cvs.info, Node: Informing others, Next: Concurrency, Prev: Conflicts example, Up: Multiple developers Informing others about commits ============================== It is often useful to inform others when you commit a new revision of a file. The `-i' option of the `modules' file, or the `loginfo' file, can be used to automate this process. *Note modules::. *Note loginfo::. You can use these features of CVS to, for instance, instruct CVS to mail a message to all developers, or post a message to a local newsgroup.  File: cvs.info, Node: Concurrency, Next: Watches, Prev: Informing others, Up: Multiple developers Several developers simultaneously attempting to run CVS ======================================================= If several developers try to run CVS at the same time, one may get the following message: [11:43:23] waiting for bach's lock in /usr/local/cvsroot/foo CVS will try again every 30 seconds, and either continue with the operation or print the message again, if it still needs to wait. If a lock seems to stick around for an undue amount of time, find the person holding the lock and ask them about the cvs command they are running. If they aren't running a cvs command, look for and remove files starting with `#cvs.tfl', `#cvs.rfl', or `#cvs.wfl' from the repository. Note that these locks are to protect CVS's internal data structures and have no relationship to the word "lock" in the sense used by RCS-a way to prevent other developers from working on a particular file. Any number of people can be reading from a given repository at a time; only when someone is writing do the locks prevent other people from reading or writing. One might hope for the following property If someone commits some changes in one cvs command, then an update by someone else will either get all the changes, or none of them. but CVS does *not* have this property. For example, given the files a/one.c a/two.c b/three.c b/four.c if someone runs cvs ci a/two.c b/three.c and someone else runs `cvs update' at the same time, the person running `update' might get only the change to `b/three.c' and not the change to `a/two.c'.  File: cvs.info, Node: Watches, Prev: Concurrency, Up: Multiple developers Mechanisms to track who is editing files ======================================== For many groups, use of CVS in its default mode is perfectly satisfactory. Users may sometimes go to check in a modification only to find that another modification has intervened, but they deal with it and proceed with their check in. Other groups prefer to be able to know who is editing what files, so that if two people try to edit the same file they can choose to talk about who is doing what when rather than be surprised at check in time. The features in this section allow such coordination, while retaining the ability of two developers to edit the same file at the same time. For maximum benefit developers should use `cvs edit' (not `chmod') to make files read-write to edit them, and `cvs release' (not `rm') to discard a working directory which is no longer in use, but CVS is not able to enforce this behavior. * Menu: * Setting a watch:: Telling CVS to watch certain files * Getting Notified:: Telling CVS to notify you * Editing files:: How to edit a file which is being watched * Watch information:: Information about who is watching and editing * Watches Compatibility:: Watches interact poorly with CVS 1.6 or earlier  File: cvs.info, Node: Setting a watch, Next: Getting Notified, Up: Watches Telling CVS to watch certain files ---------------------------------- To enable the watch features, you first specify that certain files are to be watched. - Command: cvs watch on [`-l'] FILES ... Specify that developers should run `cvs edit' before editing FILES. CVS will create working copies of FILES read-only, to remind developers to run the `cvs edit' command before working on them. If FILES includes the name of a directory, CVS arranges to watch all files added to the corresponding repository directory, and sets a default for files added in the future; this allows the user to set notification policies on a per-directory basis. The contents of the directory are processed recursively, unless the `-l' option is given. If FILES is omitted, it defaults to the current directory. - Command: cvs watch off [`-l'] FILES ... Do not provide notification about work on FILES. CVS will create working copies of FILES read-write. The FILES and `-l' arguments are processed as for `cvs watch on'.  File: cvs.info, Node: Getting Notified, Next: Editing files, Prev: Setting a watch, Up: Watches Telling CVS to notify you ------------------------- You can tell CVS that you want to receive notifications about various actions taken on a file. You can do this without using `cvs watch on' for the file, but generally you will want to use `cvs watch on', so that developers use the `cvs edit' command. - Command: cvs watch add [`-a' ACTION] [`-l'] FILES ... Add the current user to the list of people to receive notification of work done on FILES. The `-a' option specifies what kinds of events CVS should notify the user about. ACTION is one of the following: `edit' Another user has applied the `cvs edit' command (described below) to a file. `unedit' Another user has applied the `cvs unedit' command (described below) or the `cvs release' command to a file, or has deleted the file and allowed `cvs update' to recreate it. `commit' Another user has committed changes to a file. `all' All of the above. `none' None of the above. (This is useful with `cvs edit', described below.) The `-a' option may appear more than once, or not at all. If omitted, the action defaults to `all'. The FILES and `-l' option are processed as for the `cvs watch' commands. - Command: cvs watch remove [`-a' ACTION] [`-l'] FILES ... Remove a notification request established using `cvs watch add'; the arguments are the same. If the `-a' option is present, only watches for the specified actions are removed. When the conditions exist for notification, CVS calls the `notify' administrative file, passing it the user to receive the notification and the user who is taking the action which results in notification. Normally `notify' will just send an email message. Note that if you set this up in the straightforward way, users receive notifications on the server machine. One could of course write a `notify' script which directed notifications elsewhere, but to make this easy, CVS allows you to associate a notification address for each user. To do so create a file `users' in `CVSROOT' with a line for each user in the format USER:VALUE. Then instead of passing the name of the user to be notified to `notify', CVS will pass the VALUE (normally an email address on some other machine).  File: cvs.info, Node: Editing files, Next: Watch information, Prev: Getting Notified, Up: Watches How to edit a file which is being watched ----------------------------------------- Since a file which is being watched is checked out read-only, you cannot simply edit it. To make it read-write, and inform others that you are planning to edit it, use the `cvs edit' command. - Command: cvs edit [OPTIONS] FILES ... Prepare to edit the working files FILES. CVS makes the FILES read-write, and notifies users who have requested `edit' notification for any of FILES. The `cvs edit' command accepts the same OPTIONS as the `cvs watch add' command, and establishes a temporary watch for the user on FILES; CVS will remove the watch when FILES are `unedit'ed or `commit'ted. If the user does not wish to receive notifications, she should specify `-a none'. The FILES and `-l' option are processed as for the `cvs watch' commands. Normally when you are done with a set of changes, you use the `cvs commit' command, which checks in your changes and returns the watched files to their usual read-only state. But if you instead decide to abandon your changes, or not to make any changes, you can use the `cvs unedit' command. - Command: cvs unedit [`-l'] FILES ... Abandon work on the working files FILES, and revert them to the repository versions on which they are based. CVS makes those FILES read-only for which users have requested notification using `cvs watch on'. CVS notifies users who have requested `unedit' notification for any of FILES. The FILES and `-l' option are processed as for the `cvs watch' commands. When using client/server CVS, you can use the `cvs edit' and `cvs unedit' commands even if CVS is unable to succesfully communicate with the server; the notifications will be sent upon the next successful CVS command.  File: cvs.info, Node: Watch information, Next: Watches Compatibility, Prev: Editing files, Up: Watches Information about who is watching and editing --------------------------------------------- - Command: cvs watchers [`-l'] FILES ... List the users currently watching changes to FILES. The report includes the files being watched, and the mail address of each watcher. The FILES and `-l' arguments are processed as for the `cvs watch' commands. - Command: cvs editors [`-l'] FILES ... List the users currently working on FILES. The report includes the mail address of each user, the time when the user began working with the file, and the host and path of the working directory containing the file. The FILES and `-l' arguments are processed as for the `cvs watch' commands.  File: cvs.info, Node: Watches Compatibility, Prev: Watch information, Up: Watches Using watches with old versions of CVS -------------------------------------- If you use the watch features on a repository, it creates `CVS' directories in the repository and stores the information about watches in that directory. If you attempt to use CVS 1.6 or earlier with the repository, you get an error message such as cvs update: cannot open CVS/Entries for reading: No such file or directory and your operation will likely be aborted. To use the watch features, you must upgrade all copies of CVS which use that repository in local or server mode. If you cannot upgrade, use the `watch off' and `watch remove' commands to remove all watches, and that will restore the repository to a state which CVS 1.6 can cope with.  File: cvs.info, Node: Branches, Next: Merging, Prev: Multiple developers, Up: Top Branches ******** So far, all revisions shown in this manual have been on the "main trunk" of the revision tree, i.e., all revision numbers have been of the form X.Y. One useful feature, especially when maintaining several releases of a software product at once, is the ability to make branches on the revision tree. "Tags", symbolic names for revisions, will also be introduced in this chapter. * Menu: * Tags:: Tags-Symbolic revisions * Branches motivation:: What branches are good for * Creating a branch:: Creating a branch * Sticky tags:: Sticky tags  File: cvs.info, Node: Tags, Next: Branches motivation, Up: Branches Tags-Symbolic revisions ======================= The revision numbers live a life of their own. They need not have anything at all to do with the release numbers of your software product. Depending on how you use CVS the revision numbers might change several times between two releases. As an example, some of the source files that make up RCS 5.6 have the following revision numbers: ci.c 5.21 co.c 5.9 ident.c 5.3 rcs.c 5.12 rcsbase.h 5.11 rcsdiff.c 5.10 rcsedit.c 5.11 rcsfcmp.c 5.9 rcsgen.c 5.10 rcslex.c 5.11 rcsmap.c 5.2 rcsutil.c 5.10 You can use the `tag' command to give a symbolic name to a certain revision of a file. You can use the `-v' flag to the `status' command to see all tags that a file has, and which revision numbers they represent. Tag names can contain uppercase and lowercase letters, digits, `-', and `_'. The two tag names `BASE' and `HEAD' are reserved for use by CVS. It is expected that future names which are special to CVS will contain characters such as `%' or `=', rather than being named analogously to `BASE' and `HEAD', to avoid conflicts with actual tag names. The following example shows how you can add a tag to a file. The commands must be issued inside your working copy of the module. That is, you should issue the command in the directory where `backend.c' resides. $ cvs tag release-0-4 backend.c T backend.c $ cvs status -v backend.c =================================================================== File: backend.c Status: Up-to-date Version: 1.4 Tue Dec 1 14:39:01 1992 RCS Version: 1.4 /usr/local/cvsroot/yoyodyne/tc/backend.c,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none) Existing Tags: release-0-4 (revision: 1.4) There is seldom reason to tag a file in isolation. A more common use is to tag all the files that constitute a module with the same tag at strategic points in the development life-cycle, such as when a release is made. $ cvs tag release-1-0 . cvs tag: Tagging . T Makefile T backend.c T driver.c T frontend.c T parser.c (When you give CVS a directory as argument, it generally applies the operation to all the files in that directory, and (recursively), to any subdirectories that it may contain. *Note Recursive behavior::.) The `checkout' command has a flag, `-r', that lets you check out a certain revision of a module. This flag makes it easy to retrieve the sources that make up release 1.0 of the module `tc' at any time in the future: $ cvs checkout -r release-1-0 tc This is useful, for instance, if someone claims that there is a bug in that release, but you cannot find the bug in the current working copy. You can also check out a module as it was at any given date. *Note checkout options::. When you tag more than one file with the same tag you can think about the tag as "a curve drawn through a matrix of filename vs. revision number." Say we have 5 files with the following revisions: file1 file2 file3 file4 file5 1.1 1.1 1.1 1.1 /--1.1* <-*- TAG 1.2*- 1.2 1.2 -1.2*- 1.3 \- 1.3*- 1.3 / 1.3 1.4 \ 1.4 / 1.4 \-1.5*- 1.5 1.6 At some time in the past, the `*' versions were tagged. You can think of the tag as a handle attached to the curve drawn through the tagged revisions. When you pull on the handle, you get all the tagged revisions. Another way to look at it is that you "sight" through a set of revisions that is "flat" along the tagged revisions, like this: file1 file2 file3 file4 file5 1.1 1.2 1.1 1.3 _ 1.1 1.2 1.4 1.1 / 1.2*----1.3*----1.5*----1.2*----1.1 (--- <--- Look here 1.3 1.6 1.3 \_ 1.4 1.4 1.5  File: cvs.info, Node: Branches motivation, Next: Creating a branch, Prev: Tags, Up: Branches What branches are good for ========================== Suppose that release 1.0 of tc has been made. You are continuing to develop tc, planning to create release 1.1 in a couple of months. After a while your customers start to complain about a fatal bug. You check out release 1.0 (*note Tags::.) and find the bug (which turns out to have a trivial fix). However, the current revision of the sources are in a state of flux and are not expected to be stable for at least another month. There is no way to make a bugfix release based on the newest sources. The thing to do in a situation like this is to create a "branch" on the revision trees for all the files that make up release 1.0 of tc. You can then make modifications to the branch without disturbing the main trunk. When the modifications are finished you can select to either incorporate them on the main trunk, or leave them on the branch.  File: cvs.info, Node: Creating a branch, Next: Sticky tags, Prev: Branches motivation, Up: Branches Creating a branch ================= The `rtag' command can be used to create a branch. The `rtag' command is much like `tag', but it does not require that you have a working copy of the module. *Note rtag::. (You can also use the `tag' command; *note tag::.). $ cvs rtag -b -r release-1-0 release-1-0-patches tc The `-b' flag makes `rtag' create a branch (rather than just a symbolic revision name). `-r release-1-0' says that this branch should be rooted at the node (in the revision tree) that corresponds to the tag `release-1-0'. Note that the numeric revision number that matches `release-1-0' will probably be different from file to file. The name of the new branch is `release-1-0-patches', and the module affected is `tc'. To fix the problem in release 1.0, you need a working copy of the branch you just created. $ cvs checkout -r release-1-0-patches tc $ cvs status -v driver.c backend.c =================================================================== File: driver.c Status: Up-to-date Version: 1.7 Sat Dec 5 18:25:54 1992 RCS Version: 1.7 /usr/local/cvsroot/yoyodyne/tc/driver.c,v Sticky Tag: release-1-0-patches (branch: 1.7.2) Sticky Date: (none) Sticky Options: (none) Existing Tags: release-1-0-patches (branch: 1.7.2) release-1-0 (revision: 1.7) =================================================================== File: backend.c Status: Up-to-date Version: 1.4 Tue Dec 1 14:39:01 1992 RCS Version: 1.4 /usr/local/cvsroot/yoyodyne/tc/backend.c,v Sticky Tag: release-1-0-patches (branch: 1.4.2) Sticky Date: (none) Sticky Options: (none) Existing Tags: release-1-0-patches (branch: 1.4.2) release-1-0 (revision: 1.4) release-0-4 (revision: 1.4) As the output from the `status' command shows the branch number is created by adding a digit at the tail of the revision number it is based on. (If `release-1-0' corresponds to revision 1.4, the branch's revision number will be 1.4.2. For obscure reasons CVS always gives branches even numbers, starting at 2. *Note Revision numbers::).  File: cvs.info, Node: Sticky tags, Prev: Creating a branch, Up: Branches Sticky tags =========== The `-r release-1-0-patches' flag that was given to `checkout' in the previous example is "sticky", that is, it will apply to subsequent commands in this directory. If you commit any modifications, they are committed on the branch. You can later merge the modifications into the main trunk. *Note Merging::. You can use the `status' command to see what sticky tags or dates are set: $ vi driver.c # Fix the bugs $ cvs commit -m "Fixed initialization bug" driver.c Checking in driver.c; /usr/local/cvsroot/yoyodyne/tc/driver.c,v <-- driver.c new revision: 1.7.2.1; previous revision: 1.7 done $ cvs status -v driver.c =================================================================== File: driver.c Status: Up-to-date Version: 1.7.2.1 Sat Dec 5 19:35:03 1992 RCS Version: 1.7.2.1 /usr/local/cvsroot/yoyodyne/tc/driver.c,v Sticky Tag: release-1-0-patches (branch: 1.7.2) Sticky Date: (none) Sticky Options: (none) Existing Tags: release-1-0-patches (branch: 1.7.2) release-1-0 (revision: 1.7) The sticky tags will remain on your working files until you delete them with `cvs update -A'. The `-A' option retrieves the version of the file from the head of the trunk, and forgets any sticky tags, dates, or options. Sticky tags are not just for branches. If you check out a certain revision (such as 1.4) it will also become sticky. Subsequent `cvs update' will not retrieve the latest revision until you reset the tag with `cvs update -A'. Likewise, use of the `-D' option to `update' or `checkout' sets a "sticky date", which, similarly, causes that date to be used for future retrievals. Many times you will want to retrieve an old version of a file without setting a sticky tag. The way to do that is with the `-p' option to `checkout' or `update', which sends the contents of the file to standard output. For example, suppose you have a file named `file1' which existed as revision 1.1, and you then removed it (thus adding a dead revision 1.2). Now suppose you want to add it again, with the same contents it had previously. Here is how to do it: $ cvs update -p -r 1.1 file1 >file1 =================================================================== Checking out file1 RCS: /tmp/cvs-sanity/cvsroot/first-dir/Attic/file1,v VERS: 1.1 *************** $ cvs add file1 cvs add: version 1.2 of `file1' will be resurrected cvs add: use 'cvs commit' to add this file permanently $ cvs commit -m test Checking in file1; /tmp/cvs-sanity/cvsroot/first-dir/file1,v <-- file1 new revision: 1.3; previous revision: 1.2 done $  File: cvs.info, Node: Merging, Next: Recursive behavior, Prev: Branches, Up: Top Merging ******* You can include the changes made between any two revisions into your working copy, by "merging". You can then commit that revision, and thus effectively copy the changes onto another branch. * Menu: * Merging a branch:: Merging an entire branch * Merging more than once:: Merging from a branch several times * Merging two revisions:: Merging differences between two revisions  File: cvs.info, Node: Merging a branch, Next: Merging more than once, Up: Merging Merging an entire branch ======================== You can merge changes made on a branch into your working copy by giving the `-j BRANCH' flag to the `update' command. With one `-j BRANCH' option it merges the changes made between the point where the branch forked and newest revision on that branch (into your working copy). The `-j' stands for "join". Consider this revision tree: +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 ! <- The main trunk +-----+ +-----+ +-----+ +-----+ ! ! ! +---------+ +---------+ Branch R1fix -> +---! 1.2.2.1 !----! 1.2.2.2 ! +---------+ +---------+ The branch 1.2.2 has been given the tag (symbolic name) `R1fix'. The following example assumes that the module `mod' contains only one file, `m.c'. $ cvs checkout mod # Retrieve the latest revision, 1.4 $ cvs update -j R1fix m.c # Merge all changes made on the branch, # i.e. the changes between revision 1.2 # and 1.2.2.2, into your working copy # of the file. $ cvs commit -m "Included R1fix" # Create revision 1.5. A conflict can result from a merge operation. If that happens, you should resolve it before committing the new revision. *Note Conflicts example::. The `checkout' command also supports the `-j BRANCH' flag. The same effect as above could be achieved with this: $ cvs checkout -j R1fix mod $ cvs commit -m "Included R1fix"  File: cvs.info, Node: Merging more than once, Next: Merging two revisions, Prev: Merging a branch, Up: Merging Merging from a branch several times =================================== Continuing our example, the revision tree now looks like this: +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- The main trunk +-----+ +-----+ +-----+ +-----+ +-----+ ! * ! * ! +---------+ +---------+ Branch R1fix -> +---! 1.2.2.1 !----! 1.2.2.2 ! +---------+ +---------+ where the starred line represents the merge from the `R1fix' branch to the main trunk, as just discussed. Now suppose that development continues on the `R1fix' branch: +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- The main trunk +-----+ +-----+ +-----+ +-----+ +-----+ ! * ! * ! +---------+ +---------+ +---------+ Branch R1fix -> +---! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 ! +---------+ +---------+ +---------+ and then you want to merge those new changes onto the main trunk. If you just use the `cvs update -j R1fix m.c' command again, CVS will attempt to merge again the changes which you have already merged, which can have undesirable side effects. So instead you need to specify that you only want to merge the changes on the branch which have not yet been merged into the trunk. To do that you specify two `-j' options, and CVS merges the changes from the first revision to the second revision. For example, in this case the simplest way would be cvs update -j 1.2.2.2 -j R1fix m.c # Merge changes from 1.2.2.2 to the # head of the R1fix branch The problem with this is that you need to specify the 1.2.2.2 revision manually. A slightly better approach might be to use the date the last merge was done: cvs update -j R1fix:yesterday -j R1fix m.c Better yet, tag the R1fix branch after every merge into the trunk, and then use that tag for subsequent merges: cvs update -j merged_from_R1fix_to_trunk -j R1fix m.c  File: cvs.info, Node: Merging two revisions, Prev: Merging more than once, Up: Merging Merging differences between any two revisions ============================================= With two `-j REVISION' flags, the `update' (and `checkout') command can merge the differences between any two revisions into your working file. $ cvs update -j 1.5 -j 1.3 backend.c will *remove* all changes made between revision 1.3 and 1.5. Note the order of the revisions! If you try to use this option when operating on multiple files, remember that the numeric revisions will probably be very different between the various files that make up a module. You almost always use symbolic tags rather than revision numbers when operating on multiple files.  File: cvs.info, Node: Recursive behavior, Next: Adding files, Prev: Merging, Up: Top Recursive behavior ****************** Almost all of the subcommands of CVS work recursively when you specify a directory as an argument. For instance, consider this directory structure: `$HOME' | +--tc | | +--CVS | (internal CVS files) +--Makefile +--backend.c +--driver.c +--frontend.c +--parser.c +--man | | | +--CVS | | (internal CVS files) | +--tc.1 | +--testing | +--CVS | (internal CVS files) +--testpgm.t +--test2.t If `tc' is the current working directory, the following is true: * `cvs update testing' is equivalent to `cvs update testing/testpgm.t testing/test2.t' * `cvs update testing man' updates all files in the subdirectories * `cvs update .' or just `cvs update' updates all files in the `tc' module If no arguments are given to `update' it will update all files in the current working directory and all its subdirectories. In other words, `.' is a default argument to `update'. This is also true for most of the CVS subcommands, not only the `update' command. The recursive behavior of the CVS subcommands can be turned off with the `-l' option. $ cvs update -l # Don't update files in subdirectories  File: cvs.info, Node: Adding files, Next: Removing files, Prev: Recursive behavior, Up: Top Adding files to a module ************************ To add a new file to a module, follow these steps. * You must have a working copy of the module. *Note Getting the source::. * Create the new file inside your working copy of the module. * Use `cvs add FILENAME' to tell CVS that you want to version control the file. * Use `cvs commit FILENAME' to actually check in the file into the repository. Other developers cannot see the file until you perform this step. * If the file contains binary data it might be necessary to change the default keyword substitution. *Note Keyword substitution::. *Note admin examples::. You can also use the `add' command to add a new directory inside a module. Unlike most other commands, the `add' command is not recursive. You cannot even type `cvs add foo/bar'! Instead, you have to $ cd foo $ cvs add bar *Note add::, for a more complete description of the `add' command.  File: cvs.info, Node: Removing files, Next: Tracking sources, Prev: Adding files, Up: Top Removing files from a module **************************** Modules change. New files are added, and old files disappear. Still, you want to be able to retrieve an exact copy of old releases of the module. Here is what you can do to remove a file from a module, but remain able to retrieve old revisions: * Make sure that you have not made any uncommitted modifications to the file. *Note Viewing differences::, for one way to do that. You can also use the `status' or `update' command. If you remove the file without committing your changes, you will of course not be able to retrieve the file as it was immediately before you deleted it. * Remove the file from your working copy of the module. You can for instance use `rm'. * Use `cvs remove FILENAME' to tell CVS that you really want to delete the file. * Use `cvs commit FILENAME' to actually perform the removal of the file from the repository. When you commit the removal of the file, CVS records the fact that the file no longer exists. It is possible for a file to exist on only some branches and not on others, or to re-add another file with the same name later. CVS will correctly create or not create the file, based on the `-r' and `-D' options specified to `checkout' or `update'. - Command: cvs remove [`-lR'] FILES ... Schedule file(s) to be removed from the repository (files which have not already been removed from the working directory are not processed). This command does not actually remove the file from the repository until you commit the removal. The `-R' option (the default) specifies that it will recurse into subdirectories; `-l' specifies that it will not. Here is an example of removing several files: $ cd test $ rm ?.c $ cvs remove cvs remove: Removing . cvs remove: scheduling a.c for removal cvs remove: scheduling b.c for removal cvs remove: use 'cvs commit' to remove these files permanently $ cvs ci -m "Removed unneeded files" cvs commit: Examining . cvs commit: Committing . If you change your mind you can easily resurrect the file before you commit it, using the `add' command. $ ls CVS ja.h oj.c $ rm oj.c $ cvs remove oj.c cvs remove: scheduling oj.c for removal cvs remove: use 'cvs commit' to remove this file permanently $ cvs add oj.c U oj.c cvs add: oj.c, version 1.1.1.1, resurrected If you realize your mistake before you run the `remove' command you can use `update' to resurrect the file: $ rm oj.c $ cvs update oj.c cvs update: warning: oj.c was lost U oj.c  File: cvs.info, Node: Tracking sources, Next: Moving files, Prev: Removing files, Up: Top Tracking third-party sources **************************** If you modify a program to better fit your site, you probably want to include your modifications when the next release of the program arrives. CVS can help you with this task. In the terminology used in CVS, the supplier of the program is called a "vendor". The unmodified distribution from the vendor is checked in on its own branch, the "vendor branch". CVS reserves branch 1.1.1 for this use. When you modify the source and commit it, your revision will end up on the main trunk. When a new release is made by the vendor, you commit it on the vendor branch and copy the modifications onto the main trunk. Use the `import' command to create and update the vendor branch. After a successful `import' the vendor branch is made the `head' revision, so anyone that checks out a copy of the file gets that revision. When a local modification is committed it is placed on the main trunk, and made the `head' revision. * Menu: * First import:: Importing a module for the first time * Update imports:: Updating a module with the import command  File: cvs.info, Node: First import, Next: Update imports, Up: Tracking sources Importing a module for the first time ===================================== Use the `import' command to check in the sources for the first time. When you use the `import' command to track third-party sources, the "vendor tag" and "release tags" are useful. The "vendor tag" is a symbolic name for the branch (which is always 1.1.1, unless you use the `-b BRANCH' flag--*Note import options::). The "release tags" are symbolic names for a particular release, such as `FSF_0_04'. Suppose you use `wdiff' (a variant of `diff' that ignores changes that only involve whitespace), and are going to make private modifications that you want to be able to use even when new releases are made in the future. You start by importing the source to your repository: $ tar xfz wdiff-0.04.tar.gz $ cd wdiff-0.04 $ cvs import -m "Import of FSF v. 0.04" fsf/wdiff FSF_DIST WDIFF_0_04 The vendor tag is named `FSF_DIST' in the above example, and the only release tag assigned is `WDIFF_0_04'.  File: cvs.info, Node: Update imports, Prev: First import, Up: Tracking sources Updating a module with the import command ========================================= When a new release of the source arrives, you import it into the repository with the same `import' command that you used to set up the repository in the first place. The only difference is that you specify a different release tag this time. $ tar xfz wdiff-0.05.tar.gz $ cd wdiff-0.05 $ cvs import -m "Import of FSF v. 0.05" fsf/wdiff FSF_DIST WDIFF_0_05 For files that have not been modified locally, the newly created revision becomes the head revision. If you have made local changes, `import' will warn you that you must merge the changes into the main trunk, and tell you to use `checkout -j' to do so. $ cvs checkout -jFSF_DIST:yesterday -jFSF_DIST wdiff The above command will check out the latest revision of `wdiff', merging the changes made on the vendor branch `FSF_DIST' since yesterday into the working copy. If any conflicts arise during the merge they should be resolved in the normal way (*note Conflicts example::.). Then, the modified files may be committed. Using a date, as suggested above, assumes that you do not import more than one release of a product per day. If you do, you can always use something like this instead: $ cvs checkout -jWDIFF_0_04 -jWDIFF_0_05 wdiff In this case, the two above commands are equivalent.  File: cvs.info, Node: Moving files, Next: Moving directories, Prev: Tracking sources, Up: Top Moving and renaming files ************************* Moving files to a different directory or renaming them is not difficult, but some of the ways in which this works may be non-obvious. (Moving or renaming a directory is even harder. *Note Moving directories::). The examples below assume that the file OLD is renamed to NEW. * Menu: * Outside:: The normal way to Rename * Inside:: A tricky, alternative way * Rename by copying:: Another tricky, alternative way  File: cvs.info, Node: Outside, Next: Inside, Up: Moving files The Normal way to Rename ======================== The normal way to move a file is to copy OLD to NEW, and then issue the normal CVS commands to remove OLD from the repository, and add NEW to it. (Both OLD and NEW could contain relative paths, for example `foo/bar.c'). $ mv OLD NEW $ cvs remove OLD $ cvs add NEW $ cvs commit -m "Renamed OLD to NEW" OLD NEW This is the simplest way to move a file, it is not error-prone, and it preserves the history of what was done. Note that to access the history of the file you must specify the old or the new name, depending on what portion of the history you are accessing. For example, `cvs log OLD' will give the log up until the time of the rename. When NEW is committed its revision numbers will start at 1.0 again, so if that bothers you, use the `-r rev' option to commit (*note commit options::.)  File: cvs.info, Node: Inside, Next: Rename by copying, Prev: Outside, Up: Moving files Moving the history file ======================= This method is more dangerous, since it involves moving files inside the repository. Read this entire section before trying it out! $ cd $CVSROOT/MODULE $ mv OLD,v NEW,v Advantages: * The log of changes is maintained intact. * The revision numbers are not affected. Disadvantages: * Old releases of the module cannot easily be fetched from the repository. (The file will show up as NEW even in revisions from the time before it was renamed). * There is no log information of when the file was renamed. * Nasty things might happen if someone accesses the history file while you are moving it. Make sure no one else runs any of the CVS commands while you move it.  File: cvs.info, Node: Rename by copying, Prev: Inside, Up: Moving files Copying the history file ======================== This way also involves direct modifications to the repository. It is safe, but not without drawbacks. # Copy the RCS file inside the repository $ cd $CVSROOT/MODULE $ cp OLD,v NEW,v # Remove the old file $ cd ~/MODULE $ rm OLD $ cvs remove OLD $ cvs commit OLD # Remove all tags from NEW $ cvs update NEW $ cvs log NEW # Remember the tag names $ cvs tag -d TAG1 $ cvs tag -d TAG2 ... By removing the tags you will be able to check out old revisions of the module. Advantages: * Checking out old revisions works correctly, as long as you use `-rTAG' and not `-DDATE' to retrieve the revisions. * The log of changes is maintained intact. * The revision numbers are not affected. Disadvantages: * You cannot easily see the history of the file across the rename. * Unless you use the `-r rev' (*note commit options::.) flag when NEW is committed its revision numbers will start at 1.0 again.  File: cvs.info, Node: Moving directories, Next: History browsing, Prev: Moving files, Up: Top Moving and renaming directories ******************************* If you want to be able to retrieve old versions of the module, you must move each file in the directory with the CVS commands. *Note Outside::. The old, empty directory will remain inside the repository, but it will not appear in your workspace when you check out the module in the future. If you really want to rename or delete a directory, you can do it like this: 1. Inform everyone who has a copy of the module that the directory will be renamed. They should commit all their changes, and remove their working copies of the module, before you take the steps below. 2. Rename the directory inside the repository. $ cd $CVSROOT/MODULE $ mv OLD-DIR NEW-DIR 3. Fix the CVS administrative files, if necessary (for instance if you renamed an entire module). 4. Tell everyone that they can check out the module and continue working. If someone had a working copy of the module the CVS commands will cease to work for him, until he removes the directory that disappeared inside the repository. It is almost always better to move the files in the directory instead of moving the directory. If you move the directory you are unlikely to be able to retrieve old releases correctly, since they probably depend on the name of the directories.  File: cvs.info, Node: History browsing, Next: Keyword substitution, Prev: Moving directories, Up: Top History browsing **************** Once you have used CVS to store a version control history--what files have changed when, how, and by whom, there are a variety of mechanisms for looking through the history. * Menu: * log messages:: Log messages * history database:: The history database * user-defined logging:: User-defined logging * annotate:: What revision modified each line of a file?  File: cvs.info, Node: log messages, Next: history database, Up: History browsing Log messages ============ Whenever you commit a file you specify a log message. To look through the log messages which have been specified for every revision which has been committed, use the `cvs log' command (*note log::.).  File: cvs.info, Node: history database, Next: user-defined logging, Prev: log messages, Up: History browsing The history database ==================== You can use the history file (*note history file::.) to log various CVS actions. To retrieve the information from the history file, use the `cvs history' command (*note history::.).