The CVS FAQ Archive-name: cvs-faq Hand Revision: 3.5 <<== Include this in your comments Last Updated: 1995/03/09 Revision: 1.2 Date: 1995/10/26 16:06:00 =========================================================================== == Frequently Asked Questions about CVS (The Concurrent Versions System) == =========================================================================== This document attempts to answer questions posed by users of CVS. CVS installers, administrators and maintainers looking for info on system setup should read the section entitled "Installing CVS". Disclaimer: Although an attempt has been made to ensure the veracity of the following material, no responsibility is assumed for any use, or for any consequences resulting from any use, of the information contained herein. No guarantee of suitability for any purpose is offered or implied. Nothing in this document may be assumed to represent the employers of its contributors. I also might have slipped in a whopper or two to see if you are paying attention. ;-) In other words, don't bet the house on anything you read here unless you have checked it out yourself. Send questions and answers (along with additions to, subtractions from, and divisions of existing questions -- no multiplications, square roots, or transcendental functions, my cabinet is full of them) to the author, who wrote all unattributed text: (Does it always feel strange to refer to oneself in the third person?) David G. Grubbs Major revisions contain enough alterations to render change markers meaningless. (Major revisions are those with a final digit of '0', such as 2.0 or 3.0.) To help readers of previous versions of this document, minor revisions will be annotated: Change markers: Column 1 will contain a: '-' for a Question that has changed. '=' for an Answer that has changed. '#' for an entry with changes to both Question and Answer. '+' for a newly added Question and Answer. Trivial changes, such as question reordering or spelling and grammar corrections are not marked. Deleted questions will simply disappear, as will any question that can be answered by "get the latest release". Editorial comments are delimited by pairs of "[[" & "]]". They contain either references to the (usually unfinished) nature of the FAQ entry itself, version-specific comments to be removed (or altered) when new revisions of CVS are released or snide remarks from the editor. If you plan to do anything with this document other than: - Read it. - Redistribute the whole document along with the date and revision. - Post sections as answers to CVS questions (as long as you identify it as coming from the FAQ.) talk to the author first. ============================================ == Section 0 ==== Introduction ==== ============================================ The questions in this document come from many sources in many forms. Some are simple, some verbose. A few are difficult, but all of them have been asked of the author at one time or another. Some questions are really three or more different problems rolled into one plaintive cry for help. Others reveal one of the bugs or weaknesses of CVS. CVS addresses some difficult problems to which there are no perfect solutions. CVS also changes over time as new features are required. Therefore, the questions are about a complicated moving target. Though in most cases I've tried to provide the simplest answer I can think of, some of the *questions* are difficult to follow. If you aren't using CVS regularly, don't expect to understand everything. A Frequently Asked Questions document is not a substitute for the man page or any other documentation. It is an attempt to answer questions. You should also keep in mind that FAQs are not really intended to be read in their entirety like a text book. You should use "grep" or your editor's search capability to hunt for keywords and read the sections you need. Questions are divided into five numbered Sections. Sections are divided into lettered sub-sections. The questions are numbered sequentially within each sub-section, though they are in no particular order. 1. What is CVS? A. What is CVS? What's it for? Why CVS? B. Where do I find it? Where can I find Help? C. How does CVS differ from other similar software? D. What do you mean by . . .? (Definitions) 2. User Tasks A. Getting Started B. Common User Tasks C. Less Common User Tasks D. General Questions 3. Commands A. through P. One section for each CVS command. 4. Advanced Topics A. Installing CVS B. Setting up and Managing the Repository C. Branching and Merging D. Tricks of the Trade E. Internal errors F. Related Software G. Engineering H. Other Systems 5. Past & Future A. Contributors. B. Bugs and Patches C. Development D. Professional Support 6. Table of Contents Final note: Except for the "Past & Future" section, all answers in this document refer to CVS version 1.4. The latest released version is 1.5. ============================================ == Section 1 ==== What is CVS? ==== ============================================ ---------------- -- Section 1A -- What is CVS? What's it for? Why CVS? ---------------- **** Questions: 1A.1 What does CVS stand for? Can you describe it in one sentence? 1A.2 What is CVS for? What does it do for me? 1A.3 How does CVS work? 1A.4 What is CVS useful for? 1A.5 What is CVS *not* useful for? **** Answers: 1A.1 What does CVS stand for? Can you describe it in one sentence? "CVS" is an acronym for the "Concurrent Versions System". CVS is a "Source Control" or "Revision Control" tool designed to keep track of source changes made by groups of developers working on the same files, allowing them to stay in sync with each other as each individual chooses. 1A.2 What is CVS for? What does it do for me? CVS is used to keep track of collections of files in a shared directory called "The Repository". Each collection of files can be given a "module" name, which is used to "checkout" that collection. After checkout, files can be modified (using your favorite editor), "committed" back into the Repository and compared against earlier revisions. Collections of files can be "tagged" with a symbolic name for later retrieval. You can add new files, remove files you no longer want, ask for information about sets of files in three different ways, produce patch "diffs" from a base revision and merge the committed changes of other developers into your working files. 1A.3 How does CVS work? CVS saves its version-control information in RCS files stored in a directory hierarchy, called the Repository, which is separate from the user's working directory. Files in the Repository are stored in a format dictated by the RCS commands CVS uses to do much of its real work. RCS files are standard byte-stream files with an internal format described by keywords stored in the files themselves. To begin work, you execute a "checkout" command, handing it a module name or directory path (relative to the $CVSROOT variable) you want to work on. CVS copies the latest revision of each file in the specified module or directory out of the Repository and into a directory tree created in your current directory. You may specify a particular branch to work on by symbolic name if you don't want to work on the default (main or trunk) branch. You may then modify files in the new directory tree, build them into output files and test the results. When you want to make your changes available to other developers, you "commit" them back into the Repository. Other developers can check out the same files at the same time. To merge the committed work of others into your working files you use the "update" command. When your merged files build and test correctly, you may commit the merged result. This method is referred to as "copy-modify-merge", which does not require locks on the source files. At any time, usually at some milestone, you can "tag" the committed files, producing a symbolic name that can be handed to a future "checkout" command. A special form of "tag" produces a branch in development, as usually happens at "release" time. When you no longer plan to modify or refer to your local copy of the files, they can be removed. 1A.4 What is CVS useful for? CVS is intended to handle source control for files in three major situations: 1. Multiple developers working on the same files. The major advantage of using CVS over the simpler tools like RCS or SCCS is that it allows multiple developers to work on the same sources at the same time. The shared Repository provides a rendezvous for committed sources that allows developers a fair amount of flexibility in how often to publish (via the "commit" command) changes or include work committed by others (via the "update" command). 2. Tracking a stream of releases from a source vendor. If you are making changes to sources distributed by someone else, the CVS feature, called the Vendor Branch, allows you to combine local modifications with repeated vendor releases. I have found this most useful when dealing with sources from three major classes of source vendor: a. Large companies who send you tapes full of the latest release (e.g. Unix OS vendors, database companies). b. Public Domain software which *always* requires work. c. Pseudo-Public sources which may require work. (e.g. GNU programs, X, CVS itself, etc.) 3. Branching development. Aside from the "Vendor Branch", there are three kinds of "branches in development" that CVS can support: a. Your working directory can be treated as a private branch. b. A Development branch can be shared by one or more developers. c. At release time, a branch is usually created for bug fixes. (See 1D.9 and Section 4C for more info on branches.) CVS's branch support is a bit primitive, but it was designed to allow you to create branches, work on them for while and merge them back into the main line of development. You should also be able to merge work performed on the main branch into the branch you are working on. Arbitrary sharing and merging between branches is not currently supported. 1A.5 What is CVS *not* useful for? CVS is not a build system. Though the structure of your Repository and modules file interact with your build system (e.g. a tree of Makefiles), they are essentially independent. CVS does not dictate how you build anything. It merely stores files for retrieval in a tree structure you devise. CVS does not dictate how to use disk space in the checked out working directories. If you require your Makefiles or build procedures to know the relative positions of everything else, you wind up requiring the entire Repository to be checked out. That's simply bad planning. If you modularize your work, and construct a build system that will share files (via links, mounts, VPATH in Makefiles, etc.), you can arrange your disk usage however you like. But you have to remember that *any* such system is a lot of work to construct and maintain. CVS does not address the issues involved. You must use your brain and a collection of other tools to provide a build scheme to match your plans. Of course, you should use CVS to maintain the tools created to support such a build system (scripts, Makefiles, etc). CVS is not a substitute for management. You and your project leaders are expected to plan what you are doing. Everyone involved must be aware of schedules, merge points, branch names, release dates and the range of procedures needed to build products. (If you produce it and someone else uses it, it is a product.) CVS can't cover for a failure to manage your project. CVS is an instrument for making sources dance to your tune. But you are the piper and the composer. No instrument plays itself or writes its own music. CVS is not a substitute for developer communication. When faced with conflicts within a single file, most developers manage to resolve them without too much effort. But a more general definition of "conflict" includes problems too difficult to solve without communication between developers. CVS cannot determine when simultaneous changes within a single file, or across a whole collection of files, will logically conflict with one another. Its concept of a "conflict" is purely textual, arising when two changes to the same base file are near enough to spook the merge command into dropping conflict markers into the merged file. CVS is not capable of figuring out distributed conflicts in program logic. For example, if you change the arguments to function X defined in file A and, at the same time, edit file B, adding new calls to function X using the old arguments. You are outside the realm of CVS's competence. Acquire the habit of reading specs and talking to your peers. CVS is not a configuration management system. CVS is a source control system. The phrase "configuration management" is a marketing term, not an industry-recognized set of functions. A true "configuration management system" would contain elements of the following: * Source control. * Dependency tracking. * Build systems (i.e. What to build and how to find things during a build. What is shared? What is local?) * Bug tracking. * Automated Testing procedures. * Release Engineering documentation and procedures. * Tape Construction. * Customer Installation. * A way for users to run different versions of the same software on the same host at the same time. CVS provides only the first. ---------------- -- Section 1B -- Where do I find CVS? Where can I find Help? ---------------- **** Questions: 1B.1 How do I get more information about CVS? 1B.2 Is there an archive of CVS material? 1B.3 How do I get files out of the archive if I don't have FTP? 1B.4 How do I get a copy of the latest version of CVS? 1B.5 Is there a mailing list devoted to CVS? How do I find it? 1B.6 What happened to the CVS Usenet newsgroup I heard about? **** Answers: 1B.1 How do I get more information about CVS? 1. The first thing I would do is to read the Info file that comes with the CVS sources under "doc". You can format and read the cvs.texinfo file in two ways: 1. Use TeX to format it and a "dvips" command to print it and 2. Install the cvs.info files that are created by the Makefile and read them online using the Emacs "info-mode" or a stand-alone "info" reader. 2. Then I'd run "cvsinit" to set up a Repository and read the man page while trying out the commands. Type "cvs -H" for general help or "cvs -H command" for command-specific help. 3. For background, you can read the original CVS paper (in the source tree, under "doc"). It describes the purpose of CVS and some of how it was designed. Note that the emphasis of the document (especially on multiple vendors providing the same sources) is somewhat out of date. 4. For more detailed information about "internals", read the man pages for RCS. If you are a programmer, you can also read the source code to CVS. 5. Other information and tutorials may be available in the "doc" directory of the FTP archive described below. 6. For current information, and a fair amount of detail, join the info-cvs mailing list described below. 1B.2 Is there an archive of CVS material? An anonymous FTP area has been set up. It contains many of the CVS files you might want, including extra documentation, patches and a copy of the latest release. ftp ftp.delos.com >>> User: anonymous >>> Passwd: cd /pub/cvs get README get Index The README has more (and more up-to-date) information. The Index contains a terse list of what is in the archive. A WWW home page is also available at http://www.delos.com/cvs. 1B.3 How do I get files out of the archive if I don't have FTP? Use one of the FTP<->Email servers. These are the ones I've been told about: 1. FTPMAIL service is available from the same host as the FTP server described above. Send mail to "ftpmail@delos.com" containing "help" in the body of the message. For example, on most Unix systems, you can type: echo help | Mail ftpmail@delos.com The FTPMAIL server will respond with a document describing how to use the server. If the "Mail" command doesn't exist on your system, try "mailx", "/usr/ucb/mail" or "/bin/mail". 2. If you are on BITNET, use Princeton's BITFTP server. Type echo 'send help' | Mail bitftp@pucc.princeton.edu (It is likely that only BITNET addresses can use this one.) 3. Other possibilities I've heard of from the net: (Try the one closest to you.) ftpmail@decwrl.dec.com ftpmail@sunsite.unc.edu ftpmail@cs.arizona.edu ftpmail@cs.uow.edu.au ftpmail@doc.ic.ac.uk 1B.4 How do I get a copy of the latest version of CVS? The latest released version of CVS and all the programs it depends on should be available through anonymous FTP on any FSF archive. The main FSF archive is at "prep.ai.mit.edu". There are mirrors of the FSF archive on UUNET and other large Internet sites. Program(s) Suggested revision ----------- ----------------------- CVS 1.5 RCS 5.7 (latest version available today) GNU diff 2.7 (or later) [contained in diffutils-2.7] GDBM 1.5 (or later) [optional] The GNU version of diff is suggested by both the RCS and CVS configuration instructions because it works better than the standard version. It is a good idea not to accept the versions of CVS, RCS or diff you find lying on your system unless you have checked out their provenance. Using inconsistent collections of tools can cause you more trouble than you can probably afford. The FTP archive mentioned above should contain the latest official release of CVS, some official and unofficial patches and possibly complete patched versions of CVS in use somewhere. 1B.5 Is there a mailing list devoted to CVS? How do I find it? An Internet mailing list named "info-cvs" grew out of the private mailing list used by the CVS 1.3 alpha testers in early 1992. Throughout 1994, the list received an average of 100 messages per month. You can add yourself to the mailing list by sending an Email message to: info-cvs-request@prep.ai.mit.edu (Don't forget the "-request" or you'll send a message to the whole list, some of whom are capable of remote execution.) Mail to the whole list should be sent to: info-cvs@prep.ai.mit.edu An archive of the mailing list is maintained in the FTP archive mentioned above. 1B.6 What happened to the CVS Usenet newsgroup I heard about? A Usenet newsgroup named "gnu.cvs.info" was announced in April 1993, with an expected creation date of August, 1993. As of this writing (October, 1994) it hasn't appeared. If the newsgroup is ever created, it and the mailing list should be bidirectionally gatewayed, meaning that you only need access to one of them. Anything sent to the mailing list would be automatically posted to "gnu.cvs.info" and anything posted to the newsgroup would be automatically mailed to "info-cvs". A newsgroup would be easier to use than a mailing list. If the CVS newsgroup ever shows up, ask your system administrator whether you get the "gnu" hierarchy. If so, select a news reader and dive in. ---------------- -- Section 1C -- How does CVS differ from other, similar software? ---------------- This section attempts to list programs purporting to cover some of the same territory as CVS. [[These are very sparsely documented here. If you know something about one of these tools, how about trying to flesh out an entry or two?]] **** Questions: 1C.1 How does CVS differ from RCS? 1C.2 How does CVS differ from SCCS? 1C.3 How does CVS differ from ClearCase? 1C.4 How does CVS differ from TeamWare/SparcWorks? 1C.5 How does CVS differ from Aegis? 1C.6 How does CVS differ from Shapetools? 1C.7 How does CVS differ from TeamNet? 1C.8 How does CVS differ from ProFrame? 1C.9 How does CVS differ from CaseWare/CM? 1C.10 How does CVS differ from Sublime? 1C.11 How does CVS differ from PVCS? 1C.12 How does CVS differ from CMVC? **** Answers: 1C.1 How does CVS differ from RCS? CVS uses RCS to do much of its work and absolutely all the work of changing the underlying RCS files in the Repository. RCS comprises a set of programs designed to keep track of changes to individual files. Of course, it also allows you to refer to multiple files on the command line, but they are handled by iterating over individual files. There is no pretense of coordinated interaction among groups of files. CVS's main intent is to provide a set of grouping functions that allow you to treat a collection of RCS files as a single object. Of course, CVS also has to do a lot of iteration, but it tries its best to hide that it is doing so. In addition, CVS has some truly group-oriented facets, such as the modules file and the CVS administrative files that refer to a whole directory or module. One group aspect that can be a bit confusing is that a CVS branch is not the same as an RCS branch. To support a CVS branch, CVS uses "tags" (what RCS calls "symbols") and some local state, in addition to RCS branches. Other features offered by CVS that are not supported directly by RCS are 1. Automatic determination of the state of a file, (e.g. modified, up-to-date with the Repository, already tagged with the same string, etc.) which helps in limiting the amount of displayed text you have to wade through to figure out what changed and what to do next. 2. A copy-modify-merge scheme that avoids locking the files and allows simultaneous development on a single file. 3. Serialization of commits. CVS requires you to merge all changes committed (via "update") since you checked out your working copy of the file. Although it is still possible to commit a file filled with old data, it is less likely than when using raw RCS. 4. Relatively easy merging of releases from external Vendors. 1C.2 How does CVS differ from SCCS? SCCS is much closer to RCS than to CVS, so some of the previous entry applies. You might want to take a look at Walter Tichy's papers on RCS, which are referred to in the RCS man pages. [[More info here?]] 1C.3 How does CVS differ from ClearCase? ClearCase is a distributed client-server version control system. ClearCase is a variant DSEE tools, formerly available on Apollo platforms. The ClearCase tool set includes a few X-based interface tools, a command-line interface, and C programmer API. It is currently available on Sun, HP, SGI and OSF/1 platforms. ClearCase uses a special Unix filesystem type, called "mvfs" for "multi-version file system". Conceptually, mvfs adds another dimension to a regular Unix filesystem. The new axis is used to store the different versions of files and to provide a tree-hierarchical view of a collection of objects that might be scattered across any number of separate hosts on your local network. Each user acquires a "view" into the file database by creating a special mvfs mount point on their machine. Each view has a "configuration spec" containing a set of selection rules that specify the particular version of each file to make visible in that view. You can think of a "view" as a work area in CVS, except that the files don't really exist on your local disk until you modify them. This technique conserves disk space because it doesn't keep private copies of read-only files. Another advantage is that a view is "transparent" in the sense that all of the files in a "view" appear to be regular Unix files to other tools and Unix system calls. An extended naming convention allows access to particular versions of a file directly: "test.cc@@/main/bugfix/3" identifies the third version of test.c on the bugfix branch. ClearCase supports both the copy-modify-merge model of CVS (by using what are called "unreserved checkouts" and the checkin/checkout development model with file locking. Directories are version-controlled objects as well as files. A graphical merge tool is provided. Like RCS, ClearCase supports branches, symbolic tags, and delta compression. ASCII as well as binary files are supported, and converters from RCS, SCCS, DSEE formats are also included. A make-compatible build facility is provided that can identify common object code and share it among developers. A build auditing feature automatically records file dependencies by tracking every file that is opened when producing a derived object, thus making explicit dependency lists unnecessary. Pre- and post-event triggers are available for most ClearCase operations to invoke user programs or shell scripts. User-defined attributes can be assigned to any version or object. Hyper-links between version controlled objects can record their relationship. For more information, contact: Atria Software, Inc. 24 Prime Park Way Natick, MA 01760 info@atria.com (508) 650-1193 (phone) (508) 650-1196 (fax) Originally contributed by Steve Turner Edited by the author of this FAQ. 1C.4 How does CVS differ from TeamWare/SparcWorks? TeamWare is a configuration management tool from Sun Microsystems, a part of SparcWorks. It uses the same copy and merge model as CVS. The central abstraction is a workspace, which corresponds to either a CVS branch or a checked out module. TeamWare allows you to manipulate workspaces directly, including moving and merging code between workspaces. You can put your workspace on tape and continue to work with it at home, just like you can with CVS. TeamWare is built upon and compatible with SCCS. TeamWare provides both a command line interface and a graphical interface. The CodeManager tool will display the project as a tree of workspaces, and allows you to manipulate them with drag and drop. The other tools are VersionTool that displays and manipulates a dag with a version history of a single file, CheckPoint that will create symbolic tags, MakeTool, a make compatible tool with a GUI, and FileMerge which will interactively merge files when needed (like emerge for emacs). If you have a sun, you can try /usr/old/mergetool for an old SunView version of FileMerge. Email: sunprosig@sun.com Originally extracted from TeamWare Marketing literature by Per Abrahamsen. Edited by the author of this FAQ. For more information, contact: SunExpress, Inc. P.O. Box 4426 Bridgeton, MO 63044-9863 (800)873-7869 1C.5 How does CVS differ from Aegis? Aegis appears to be a policy-setting tool that allows you to use other sub-programs (make, RCS, etc.) to implement pieces of the imposed policy. The initial document seems to say that most Unix tools are inadequate for use under Aegis. It is not really similar to CVS and requires a different mindset. [[Need more info here.]] 1C.6 How does CVS differ from Shapetools? Shapetools includes a build mechanism (called Shape, not surprisingly) that is aware of the version mechanism, and some dependency tracking. It is based on a file system extension called Attributed File System, which allows arbitrary-sized "attributes" to be associated with a file. Files are version controlled in a manner similar to RCS. Configurations are managed through the Shapefile, an extension of the Makefile syntax and functionality. Shape includes version selection rules to allow sophisticated selection of component versions in a build. Shapetools' concurrency control is pessimistic, in contrast to that of CVS. Also, there's very limited support for branching and merging. It has a built-in policy for transitioning a system from initial development to production. Contributed by Don Dwiggins 1C.7 How does CVS differ from TeamNet? TeamNet is a configuration management tool from TeamOne. For more information, contact: TeamOne 710 Lakeway Drive, Ste 100 Sunnyvale, CA 94086 (800) 442-6650 Contributed by Steve Turner 1C.8 How does CVS differ from ProFrame? ProFrame is a new system integration framework from IBM. ProFrame is compliant with the CFI (CAD Framework Initiative) industry standards, including the Scheme extension language. ProFrame consists of three major components: (1) the Process Manager that automates your local design methodology (2) the Design Data Manager handles configuration management, and (3) Inter-tool Communication to provide a communication path among tools running on heterogeneous servers. The Design Data Manager(2) is probably the appropriate component to compare to CVS. The Design Data Manager provides version control with checkin/checkout capability, configuration management, and data dependency tracking. A graphical data selection interface is provided. Using this interface, you may create and manipulate objects and hierarchy structures, view the revision history for an object, and view and assign attributes to a design object. The ProFrame server currently runs only on RS6000, but clients may be a wide variety of Unix platforms. Contact IBM for the latest platform information. For more information, contact: IBM EDA Marketing and Sales P.O. Box 950, M/S P121 Poughkeepsie, NY 12602 (800) 332-0066 Contributed by Steve Turner [extracted from the ProFrame 1.1.0 datasheet] 1C.9 How does CVS differ from CaseWare/CM? CaseWare/CM is a software configuration management product from CaseWare, Inc. CaseWare/CM may be customized to support a wide variety of methodologies, including various phases of the software lifecycle, and different access rights for users. A GUI is provided to view version histories and configurations. A merge tools is also included. CaseWare supports type-specific lifecycles, which allows different types of files to move through different lifecycles. Also provided is a build facility to support automatic dependency analysis, parallel, distributed, and remote builds, and variant releases. CaseWare/CM has been integrated with other CASE tools, including FrameMaker, ALSYS Ada, CodeCenter/Object Center, HP SoftBench, and Software Through Pictures. CaseWare also offers CaseWare/PT, a problem tracking system to integrate change requests with configuration management. Multiple vendors and operating systems are supported. For more information, contact: CaseWare, Inc. 108 Pacifica, 2nd Floor Irvine, CA 92718-3332 (714) 453-2200 (phone) (714) 453-2276 (fax) Contributed by Steve Turner [extracted from the CaseWare/CM data sheet] 1C.10 How does CVS differ from Sublime? Produced by AT&T. [[Need more info here.]] 1C.11 How does CVS differ from PVCS? PVCS works on single files like RCS and SCCS, CVS works on complete subsystems. PVCS has a make utility (called a configuration builder), CVS does not. PVCS has a GUI interface for Unix, DOS, OS/2, and MS Windows. Intersolv, Inc. 1700 NW 167th Place OR 97006 Contributed by Per Abrahamsen [Extracted from Intersolv Marketing literature.] 1C.12 How does CVS differ from CMVC? CMVC is an IBM Configuration Management and Version Control system. (Though I'm not certain that's the right acronym expansion.) It runs on Suns, HPs, RS6000s, OS/2 and Windows. Other than revision control, it apparently has features to manage releases, bug tracking and the connection between alterations and reported bugs and feature requests. It is a client/server system, based on a choice of commercial Relational Database systems, and it provides a Motif or command line interface. Unlike CVS, it uses a strict locking protocol to serialize source code alterations. ---------------- -- Section 1D -- What do you mean by . . .? (Definitions) ---------------- **** Questions: 1D.1 What are "The Repository", "$CVSROOT" and "CVSROOT"? 1D.2 What is an RCS file? 1D.3 What is a working file? 1D.4 What is a working directory (or working area)? 1D.5 What is "checking out"? 1D.6 What is a revision? 1D.7 What is a "Tag"? 1D.8 What are "HEAD" and "BASE"? 1D.9 What is a Branch? 1D.10 What is "the trunk"? 1D.11 What is a module? 1D.12 What does "merge" mean? **** Answers: 1D.1 What are "The Repository", "$CVSROOT" and "CVSROOT"? The Repository is a directory tree containing the CVS administrative files and all the RCS files that constitute "imported" or "committed" work. The Repository is kept in a shared area, separate from the working areas of all developers. Users of CVS must set their "CVSROOT" environment variable to the absolute pathname of the head of the Repository. Most command line interpreters replace an instance of "$CVSROOT" with the value of the "CVSROOT" environment variable. By analogy, in this document "$CVSROOT" is used as shorthand for "the absolute pathname of the directory at the head of the Repository". One of the things found in $CVSROOT is a directory named CVSROOT. It contains all the "state", the administrative files, that CVS needs during execution. The "modules", "history", "commitinfo", "loginfo" and other files can be found there. See 4B.2 for more information about CVSROOT files. 1D.2 What is an RCS file? An RCS file is a text file containing the source text and the revision history for all committed revisions of a source file. It is stored separately from the working files, in a directory hierarchy, called the Repository. RCS is the "Revision Control System" that CVS uses to manage individual files. RCS file names normally end in ",v", but that can be altered (via the RCS -x option) to conform to file naming standards on platforms with unusual filename limitations. 1D.3 What is a working file? A working file is a disk file containing a checked-out copy of a source file that earlier had been placed under CVS. If the working file has been edited, the changes since the last committed revision are invisible to other users of CVS. 1D.4 What is a working directory (or working area)? A working directory is the place where you work and the place from which you "commit" files. The "checkout" command creates a tree of working directories, filling them with working files. Each working directory contains a sub-directory named ./CVS containing three administrative files, which are created by "checkout" and are always present: ./CVS/Entries contains information about working files. ./CVS/Repository contains the location of the directory within the Repository that was used to create the working directory. ./CVS/Root contains the value of $CVSROOT at the time you created the working directory. Other files may also appear in ./CVS depending on the state of your working directory: ./CVS/Tag contains the "sticky tag" associated with the whole directory. See 3A.2 for its main purpose. [Created by "checkout" or "update" when using "-r ".] [Deleted by "checkout" or "update" when using '-A'.] ./CVS/Entries.Static contains a fixed list of working files. If this file exists, an "update" doesn't automatically bring newly added files out of the Repository. [Created and maintained by hand.] ./CVS/Checkin.prog contains a program to run whenever anything in the working directory is committed. [Created by checkout if "-i " appears in the modules file for the checked-out module.] ./CVS/Update.prog contains a program to run whenever anything in the working directory is updated. [Created by checkout if "-u " appears in the modules file for the checked-out module.] ./CVS/,p ./CVS/,t contain (possibly zero-length) state information about an "add" that has not been committed. [Created by "add".] [Deleted by "commit" or "remove".] 1D.5 What is "checking out"? "Checking out" is the act of using the "checkout" command to copy a particular revision from a set of RCS files into your working area. You normally execute "checkout" only once per working directory (or tree of working directories), maintaining them thereafter with the "update" command. See section 3C on the "checkout" command. 1D.6 What is a revision? A "revision" is a version of a file that was "committed" ("checked in", in RCS terms) some time in the past. CVS (and RCS) can retrieve any file that was committed by specifying its revision number or its "tag" ("symbolic name", in RCS terms). In CVS, a "tag" is more useful than a revision number. It usually marks a milestone in development represented by different revision numbers in different files, all available as one "tagged" collection. Sometimes the word "revision" is used as shorthand for "the file you get if you retrieve (via "checkout" or "update") the given revision from the Repository." 1D.7 What is a "Tag"? A "Tag" is a symbolic name, a synonym or alias for a particular revision number in a file. The CVS "tag" command places the same "Tag" on all files in a working directory, allowing you to retrieve those files by name in the future. The CVS "Tag" is implemented by applying RCS "symbols" to each individual file. The Tags on a file (or collection of files) may be displayed using the "log" command. 1D.8 What are "HEAD" and "BASE"? HEAD and BASE are built-in tags that don't show up in the "log" or "status" listings. They are interpreted directly by CVS. "HEAD" refers to the latest revision on the current branch in the Repository. The current branch is either the main line of development, or a branch in development created by placing a branch tag on a set of files and checking out that branch. "BASE" refers to the revision on the current branch you last checked out, updated, or committed. If you have not modified your working file, "BASE" is the committed revision matching it. Most of the time BASE and HEAD refer to the same revision. They can become different in two ways: 1. Someone else changed HEAD by committing a new revision of your file to the Repository. You can pull BASE up to equal HEAD by executing "update". 2. You moved BASE backward by executing "checkout" or "update" with the option "-r " or "-D ". CVS records a sticky tag and moves your files to the specified earlier revision. You can clear the sticky tag and pull BASE up to equal HEAD again by executing "update -A". 1D.9 What is a Branch? In general, a branch is any mechanism that allows one or more developers to modify a file without affecting anyone other than those working on the same branch. There are four kinds of "branch" CVS can manage: 1. The Vendor Branch. A single vendor branch is supported. The "import" command takes a sequence of releases from a source code vendor (called a "vendor" even if no money is involved), placing them on a special "Vendor" branch. The Vendor branch is considered part of the "Main line" of development, though it must be merged into locally modified files on the RCS Main branch before the "import" is complete. See Section 3H ("import"). 2. Your Working directory. A checked-out working directory, can be treated like a private branch. No one but you can touch your files. You have complete control over when you include work committed by others. However, you can't commit or tag intermediate versions of your work. 3. A Development branch. A group of developers can share changes among the group, without affecting the Main line of development, by creating a branch. Only those who have checked-out the branch see the changes committed to that branch. This kind of branch is usually temporary, collapsing (i.e. merge and forget) into the Main line when the project requiring the branch is completed. You can also create a private branch of this type, allowing an individual to commit (and tag) intermediate revisions without changing the Main line. It should be managed exactly like a Development Branch -- collapsed into the Main line (or its parent branch, if that is not the Main Branch) and forgotten when the work is done. 4. A Release branch. At release time, a branch should be created marking what was released. Later, small changes (sometimes called "patches") can be made to the release without including everything else on the Main line of development. You avoid forcing the customer to accept new, possibly untested, features added since the release. This is also the way to correct bugs found during testing in an environment where other developers have continued to commit to the Main line while you are testing and packaging the release. Although the internal format of this type of branch (branch tag and RCS branches) is the same as in a development branch, its purpose and the way it is managed are different. The major difference is that a Release branch is normally Permanent. Once you let a release out the door to customers, or to the next stage of whatever process you are using, you should retain forever the branch marking that release. Since the branch is permanent, you cannot incorporate the branch fixes into the Main line by "collapsing" (merging and forgetting) the release branch. For large changes to many files on the release branch, you will have to perform a branch merge using "update -j -j ". (See 4C.7) The most common way to merge small changes back into Main line development is to make the change in both places simultaneously. This is faster than trying to perform a selective merge. See 1D.12 (merges) and Section 4C, on Branching for more info. 1D.10 What is "the trunk"? Another name for the RCS Main Branch. The RCS Main Branch is related, but not equivalent, to both the CVS Main branch and what developers consider to be the Main line of development. See 3H.3 and Section 4C on Branching. 1D.11 What is a module? In essence, a module is a name you hand to the "checkout" command to retrieve one or more files to work on. It was originally intended to be a simple, unique name in the "modules" file attached to a directory or a subset of files within a directory. The module idea is now a somewhat slippery concept that can be defined in two different ways: A. A module is an argument to "checkout". There are three types: 1. An entry in the modules file. A "module" name as described in 'B.' below. 2. A relative path to a directory or file in the Repository. 3. A mixed-mode string of "modulename/relative-path". Everything up to the first slash ('/') is looked up as a module. The relative path is appended to the directory associated with the module name and the resulting path is checked out as in #2 above. B. A module is a unique (within the file) character string in the first column of the modules file. There are five types: 1. A name for a directory within the Repository that allows you to ignore the parent directories above it. Example: emacs gnu/emacs 2. A name for a subset of the files within such a directory. Example: ls unix/bin Makefile ls.c The 2nd through Nth strings in the above can be files, directories or module substitutions. No relative paths. A module substitution occurs when you use a '&module-name' reference. The module-name referred to is logically substituted for the '&module-name' string. 3. A relative pathname to a directory within the Repository which, when checked out, creates an image of part of the Repository structure in your current directory. Example: gnu/emacs -o /bin/emacs.helper gnu/emacs The files checked out are exactly the same as the files "checkout" would retrieve if the path weren't even in the modules file. The only reason to put this kind of relative pathname into the modules file is to hook one of the helper functions onto it. 4. A relative pathname to a single file within the Repository which, when checked out, creates something you probably don't want: It creates a directory by the name of the file and puts the file in it. Example: gnu/emacs/Makefile -o /bin/emacs.helper gnu/emacs Makefile The file checked out is the same as what you would get if you handed the relative pathname to the "checkout" command. But it puts it in a strange place. The only reason to do this is to hook a helper function onto a specific file name. 5. An alias consisting of a list of any of the above, including other aliases, plus exceptions. Example: my_work -a emacs !emacs/tests gnu/bison unix/bin/ls.c The exception "!emacs/test" above is functionally equivalent to specifying "!emacs/tests" on the "checkout" command line. Another way to look at it is that the modules file is simply another way to "name" files. The hierarchical directory structure provides another. You should use whatever turns out to be simplest for your development group. See 4G.2 for some specific ideas about how to use the modules file. 1D.12 What does "merge" mean? A merge is a way of combining changes made in two independent copies of a common starting file. Checking out an RCS revision produces a file, so for the purposes of a merge "file" and "revision" are equivalent. So, we can say there are always three "files" involved in a merge: 1. The original, starting, "base" or "branch point" file. 2. A copy of the base file modified in one way. 3. Another copy of the base file modified in a different way. Humans aren't very good at handling three things at once, so the terminology dealing with merges can become strained. One way to think about it is that all merges are performed by inserting the difference between a base revision and a later revision (committed by someone else) into your working file. Both the "later" revision and your working file are presumed to have started life as a copy of the "base" revision. In CVS, there are three main types of "merge": 1. The "update" command automatically merges revisions committed by others into your working file. In this case, the three files involved in the merge are: Base: The revision you originally checked out. Later: A revision committed onto the current branch after you checked out the Base revision. Working: Your working file. The one lying in the working directory containing changes you have made. 2. The "update -j {optional files}" command merges changes made on the given branch into your working files, which is presumed to be on the Main line of development. See 4C.6 3. The "update -j -j {optional files}" command merges the difference between two specified revisions into files in your working directory. The two revisions are usually on the same branch and, when updating multiple files, they are most useful when they are Tag names rather than numeric revisions. See 4C.7 ========================================== == Section 2 ==== User Tasks ==== ========================================== ---------------- -- Section 2A -- Getting Started ---------------- **** Questions: 2A.1 What is the first thing I have to know? 2A.2 Where do I work? 2A.3 What does CVS use from my environment? 2A.4 OK, I've been told that CVS is set up, my module is named "ralph" and I have to start editing. What do I type? 2A.5 I have been using RCS for a while. Can I convert to CVS without losing my revision history? How about converting from SCCS? **** Answers: 2A.1 What is the first thing I have to know? Your organization has most likely assigned one or more persons to understand, baby-sit and administer the CVS programs and the data Repository. I call these persons Repository Administrators. They should have set up a Repository and "imported" files into it. If you don't believe anyone has this responsibility, or you are just testing CVS, then *you* are the Repository Administrator. If you are a normal user of CVS ask your Repository Administrator what module you should check out. Then you can work. If you *are* the Repository Administrator, you will want to read everything you can get your hands on, including this FAQ. Source control issues can be difficult, especially when you get to branches and release planning. Expect to feel stupid for a few days/weeks. No tool in the universe avoids the need for intelligent organization. In other words, there are all sorts of related issues you will probably have to learn. Don't expect to dive in without any preparation, stuff your 300 Megabytes of sources into CVS and expect to start working. If you don't prepare first, you will probably spend a few sleepless nights. 2A.2 Where do I work? Wherever you have disk space. That's one of the advantages of CVS: you use the "checkout" command to copy files from the Repository to your working directory, which can be anywhere you have the space. Your local group might have conventions for where to work. Ask your peers. 2A.3 What does CVS use from my environment? You must set two environment variables. Some shells share these variables with local shell variables using a different syntax. You'll have to learn how your shell handles them. Variable Value (or action) --------- --------------------- CVSROOT Absolute pathname of the head of your Repository. PATH Normally set to a list of ':'-separated directory pathnames searched to find executables. You must make sure "cvs" is in one of the directories. If your CVS was built with the RCSBIN directory set to null (""), and you don't set the RCSBIN variable mentioned below, then the RCS commands also must be somewhere in your PATH. Optional variables: (Used if set, but ignored otherwise.) Variable Value (or action) --------- --------------------- CVSEDITOR The name of your favorite fast-start editor program. You'll be kicked into your editor to supply revision comments if you don't specify them via -m "Log message" on the command line. EDITOR Used if CVSEDITOR doesn't exist. If EDITOR doesn't exist, CVS uses a configured constant, usually, "vi". CVSREAD Sets files to read-only on "checkout". RCSBIN Changes where CVS finds the RCS commands. CVSIGNORE Adds to the ignore list. See Section 2D. Other variables used by CVS that are normally set upon login: Variable Value (or action) --------- --------------------- LOGNAME Used to find the real user name. USER Used to find the real user name if no LOGNAME. HOME Used to determine your home directory, if set. Otherwise LOGNAME/USER/getuid() are used to find your home directory from the passwd file. TMPDIR Used during import. It might also be used if your platform's version of mktemp(3) is unusual, or you have changed the source to use tmpnam(3). 2A.4 OK, I've been told that CVS is set up, my module is named "ralph" and I have to start editing. What do I type? cd cvs checkout ralph cd ralph And hack away. 2A.5 I have been using RCS for a while. Can I convert to CVS without losing my revision history? How about converting from SCCS? If you are asking such questions, you are not a mere user of CVS, but one of its Administrators! You should take a look at Section 4A, "Installing CVS" and Section 4B, "Setting up and Managing the Repository". ---------------- -- Section 2B -- Common User Tasks ---------------- What I consider a "common user task" generally involves combinations of the following commands: checkout, update, commit, diff, log, status, tag, add Conventions in this section: 1. Before each CVS command, you are assumed to have typed a "cd" command to move into a writable working directory. 2. All further "cd" commands specified in the examples are assumed to start in the above working directory. 3. Unless a point is being made about multiple instances, all modules are named , all tags are named (branch tags are named ) and all files are named . The checkout command will take a relative path name in place of a module name. If you use a relative pathname in place of , you should use the same relative path every place you see in that example. **** Questions: 2B.1 What is the absolute minimum I have to do to edit a file? 2B.2 If I edit multiple files, must I type "commit" for each one? 2B.3 How do I get rid of the directory that "checkout" created? 2B.4 How do I find out what has changed since my last update? 2B.5 I just created a new file. How do I add it to the Repository? 2B.6 How do I merge changes made by others into my working directory? 2B.7 How do I label a set of revisions so I can retrieve them later? 2B.8 How do I checkout an old release of a module, directory or file? 2B.9 What do I have to remember to do periodically? **** Answers: 2B.1 What is the absolute minimum I have to do to edit a file? Tell your Repository Administrator to create a module covering the directory or files you care about. You will be told that your module name is . Then type: cvs checkout cd emacs # Isn't Emacs a synonym for edit? cvs commit If you don't use modules (in my opinion, a mistake), you can check out a directory by substituting its relative path within the Repository for in the example above. To work on a single file, you'll have to change "cd " to "cd `dirname `". 2B.2 If I edit multiple files, must I type "commit" for each one? No. You can commit a list of files and directories, including relative paths into multiple directories. You can also commit every modified file in the current directory or in all directories and subdirectories from your current directory downward. See 3D.2. 2B.3 How do I get rid of the directory that "checkout" created? Change your directory to be the same as when you executed the "checkout" command that created . If you want to get rid of the CVS control information, but leave the files and directories, type: cvs release If you want to obliterate the entire directory, type: cvs release -d ("release -d" searches through the output of "cvs -n update" and refuses to continue if the "update" command finds any modified files or non-ignored foreign files. Foreign directories too.) If you don't care about keeping "history", or checking for modified and foreign files, you can just remove the whole directory. That's "rm -rf " under Unix. 2B.4 How do I find out what has changed since my last update? There are many ways to answer this. To find out what you've changed in your current working directory since your last checkout, update or commit, type: cvs diff To find out what other people have added (to your branch) since you last checked out or updated, type: cvs diff -r BASE -r HEAD To look at a revision history containing the comments for all changes, you can use the "log" command. You can also use "history" to trace a wide variety of events. 2B.5 I just created a new file. How do I add it to the Repository? The "update" command will mark files CVS doesn't know about in your working directory with a '?' indicator. ? To add to the Repository, type: cvs add cvs commit See 3A.[2-5] and 4C.8 for branch and merge considerations. 2B.6 How do I merge changes made by others into my working directory? If you are asking about other branches, see Section 4C on "Branching". You will have to use the "update -j" command. Retrieving changes made to the Repository on the *same* branch you are working on is the main purpose of the "update" command. The "update" command tries to merge work committed to the Repository by others since you last executed "checkout", "update" or "commit" into your working files. For a single file, there are six possible results when you type the "update" command: 1. If the file is lying in your working directory, but is not under CVS, it will do nothing but print: ? 2. If neither you nor anyone else has committed changes to , since your last "checkout", "update" or "commit", "update" will print nothing and do nothing. 3. If you have made no changes to a working file, but you or others have committed changes to the Repository since your last "checkout", "update" or "commit" of this working file, CVS will remove your working file and replace it with a copy of the latest revision of that file in the Repository. It will print: U You might want to examine the changes (using the CVS "diff" command) to see if they mesh with your own in related files. 4. If you have made changes to a working file, but no one has changed your BASE revision (the revision you retrieved from the Repository in your last "checkout", "update" or "commit"), "update" will print: M Nothing changes. You were told that you have a modified file in your directory. 5. If you have made changes to your working file and you or others have committed changes to the Repository, but in different sections of the file, CVS will merge the changes stored in the Repository since your last "checkout", "update" or "commit" into your working file. "update" will print: RCS file: /Repository/module/ retrieving revision 1.X retrieving revision 1.Y Merging differences between 1.X and 1.Y into M If you execute "diff" before and after this step, you should see the same output, since both the base file and your working file changed in parallel. This is one of the few times the otherwise nonsensical phrase "same difference" means something. 6. If both you and those who committed files (since your last checkout, update or commit) have made changes to the same section of a file, CVS will merge the changes into your file as in #5 above, but it will leave conflict indicators in the file. "update" will print: RCS file: /Repository/module/ retrieving revision 1.X retrieving revision 1.Y Merging differences between 1.X and 1.Y into rcsmerge warning: overlaps during merge cvs update: conflicts found in C This is a "conflict". The file will contain markers surrounding the overlapping text. The 'C' conflict indicator is sticky -- subsequent "update" commands will continue to show a 'C' until you edit the file. You must examine the overlaps with care and resolve the problem by analyzing how to retain the features of both changes. See 2D.7 and 3P.6 for more details on conflict resolution. 2B.7 How do I label a set of revisions so I can retrieve them later? To "tag" the BASE revisions (the ones you last checked out, updated, or committed) you should "cd" to the head of the working directory you want to tag and type: cvs tag It recursively walks through your working directory tagging the BASE revisions of all files. To "tag" the latest revision on the Main branch in the Repository, you can use the following from anywhere: (No "cd" is required -- it works directly on the Repository.) cvs rtag 2B.8 How do I checkout an old release of a module, directory or file? Module names and directories are simply ways to name sets of files. Once the names are determined, there are 6 ways to specify which revision of a particular file to check out: 1. By tag or symbolic name, via the "-r " option. 2. By date, via the "-D " option. 3. By branch tag (a type of tag with a magic format), via the "-r " option. 4. By date within a branch, via the "-r :" option. 5. By an explicit branch revision number ("-r "), which refers to the latest revision on the branch. This isn't really an "old" revision, from the branch's perspective, but from the user's perspective the whole branch might have been abandoned in the past. 6. An explicit revision number: "-r " Though this works, it is almost useless for more than one file. You type: cvs checkout cd 2B.9 What do I have to remember to do periodically? You should execute "cvs -n update" fairly often to keep track of what you and others have changed. It won't change anything -- it will just give you a report. Unless you are purposely delaying the inclusion of others' work, you should execute "update" once in a while and resolve the conflicts. It is not good to get too far out of sync with the rest of the developers working on your branch. It is assumed that your system administrators have arranged for editor backup and Unix temp files (#* and .#*) to be deleted after a few weeks. But you might want to look around for anything else that is ignored or hidden. Try "cvs -n update -I !" to see all the ignored files. If you are the Repository Administrator, see 4B.16 on Administrator responsibilities. ---------------- -- Section 2C -- Less Common User Tasks ---------------- What I consider a "less common user task" generally involves one or more of the following commands: history, import, export, rdiff, release, remove, rtag **** Questions: 2C.1 Can I create non-CVS sub-directories in my working directory? 2C.2 How do I add new sub-directories to the Repository? 2C.3 How do I remove a file I don't need? 2C.4 How do I rename a file? 2C.5 How do I make sure that all the files and directories in my working directory are really in the Repository? 2C.6 How do I create a branch? 2C.7 How do I modify the modules file? How about the other files in the CVSROOT administrative area? 2C.8 How do I split a file into pieces, retaining revision histories? **** Answers: 2C.1 Can I create non-CVS sub-directories in my working directory? Yes. Unless the directory exists in the Repository, "update" will skip over them and print a '?' the way it does for files you forgot to add. You can avoid seeing the '?' by adding the name of the foreign directory to the ./.cvsignore file, just ask you can do with files. If you explicitly mention a foreign directory on the "update" command line, it will traverse the directory and waste a bit of time, but if any directory or sub-directory lacks the ./CVS administrative directory, CVS will print an error and abort. 2C.2 How do I add new sub-directories to the Repository? The "add" command will work on directories. You type: mkdir cvs add It will respond: Directory /Repos/ added to the repository and will create both a matching directory in the Repository and a ./CVS administrative directory within the local directory. 2C.3 How do I remove a file I don't need? (See the questions in Section 4B on removing files from the Repository.) You type: rm cvs remove CVS registers the file for removal. To complete the removal, you must type: cvs commit CVS moves the file to the Attic associated with your working directory. Each directory in the Repository stores its deleted files in an Attic sub-directory. A normal "checkout" doesn't look in the Attic, but if you specify a tag, a date or a revision, the "checkout" (or "update") command will retrieve files from the Attic with that tag, date or revision. 2C.4 How do I rename a file? CVS does not offer a way to rename a file in a way that CVS can track later. See Section 4B for more information. Here is the best (to some, the only acceptable) way to get the effect of renaming, while preserving the change log: 1. Copy the RCS (",v") file directly in the Repository. cp $CVSROOT//,v $CVSROOT//,v By duplicating the file, you will preserve the change history and the ability to retrieve earlier revisions of the old file via the "-r " or "-D " options to "checkout" and "update". 2. Remove the old file using CVS. cd / rm cvs remove cvs commit This will move the to the Attic associated with . 3. Retrieve and remove all the Tags from it. By stripping off all the old Tags, "checkout -r" and "update -r" won't retrieve revisions Tagged before the renaming. cd / cvs update cvs log # Save the list of Tags cvs tag -d cvs tag -d . . . This technique can be used to rename files within one directory or across different directories. You can apply this idea to directories too, as long as you apply the above to each file and don't delete the old directory. Of course, you have to change your build system (e.g. Makefile) in your to know about the name change. Warning: Stripping the old tags from the copied file will allow "-r " to do the right thing, but you will still have problems with "-D " because there is no place to store the "deletion time". See 5B.3 for more details. 2C.5 How do I make sure that all the files and directories in my working directory are really in the Repository? A "cvs update", or "cvs -n update" (which won't modify your working directory) will display foreign elements, which have no counterpart in the Repository, preceded by a '?'. To register foreign directories, you can use "cvs add". To register foreign files, you can use "cvs add" followed by "cvs commit". You could also checkout your module, or the Repository directory associated with your working directory, a second time into another work area and compare it to your working directory using the (non-CVS) "diff -r" command. By default many patterns of files are ignored. If you create a file named "core" or a file ending in ".o", it is usually ignored. If you really want to see all the files that aren't in the Repository, you can use a special "ignore" pattern to say "ignore no files". Try executing: (You may have to quote or backwhack (i.e. precede by '\') the '!' in your shell.) cvs -n update -I ! The above command will display not only the normal modified, update and conflict indicators ('M', 'U', and 'C' respectively) on files within the Repository, but it will also display each file not in the Repository preceded by a '?' character. The '-n' option will not allow "update" to alter your working directory. 2C.6 How do I create a branch? Type this in your working directory: cvs tag -b and you will create a branch. No files have real branches in them yet, but if you move onto the branch by typing: cvs update -r and commit a file in the normal way: cvs commit then a branch will be created in the underlying ,v file and the new revision of will appear only on that branch. See Section 4C, on Branching. 2C.7 How do I modify the modules file? How about the other files in the CVSROOT administrative area? A module named "modules" has been provided in the default modules file, so you can type: cvs checkout modules cd modules Another module named CVSROOT has been provided in the default modules file, covering all the administrative files. Type: cvs checkout CVSROOT cd CVSROOT Then you can edit your files, followed by: cvs commit If you start with the provided template for the "modules" file, the CVSROOT and the "modules" module will have the "mkmodules" program as a "commit helper". After a file is committed to such a module, "mkmodules" will convert a number of standard files (See 4B.2) in the CVSROOT directory inside the Repository into a form that is usable by CVS. 2C.8 How do I split a file into pieces, retaining revision histories? If you and a coworker find yourselves repeatedly committing the same file, but never for changes in the same area of the file, you might want to split the file into two or more pieces. If you are both changing the same section of code, splitting the file is of no use. You should talk to each other instead. If you decide to split the file, here's a suggestion. In many ways, it is similar to multiple "renamings" as described in 2C.4 above. Say you want to split , which already in the Repository, into three pieces, , and . 1. Copy the RCS (",v") files directly in the Repository, creating the new files, then bring readable copies of the new files into the working directory via "update". cp $CVSROOT//,v $CVSROOT//,v cp $CVSROOT//,v $CVSROOT//,v cvs update 2. Then remove all the from the new files by using: cvs log # Save the list of cvs tag -d cvs tag -d . . . 3. Edit each file until it has the data you want in it. This is a hand-editing job, not something CVS can handle. Then commit all the files. [From experience, I'd suggest making sure that only one copy of each line of code exists among the three files, except for "include" statements, which must be duplicated. And make sure the code compiles.] emacs cvs commit As in the "rename" case, by duplicating the files, you'll preserve the change history and the ability to retrieve earlier revisions. Of course, you have to alter your build system (e.g. Makefiles) to take the new names and the change in contents into account. ---------------- -- Section 2D -- General Questions ---------------- **** Questions: 2D.1 How do I see what CVS is trying to do? 2D.2 If I work with multiple modules, should I check them all out and commit them occasionally? Is it OK to leave modules checked out? 2D.3 What is a "sticky" tag? What makes it sticky? How do I loosen it? 2D.4 How do I get an old revision without updating the "sticky tag"? 2D.5 What operations disregard sticky tags? 2D.6 Is there a way to avoid reverting my Emacs buffer after committing a file? Is there a "cvs-mode" for Emacs? 2D.7 How does conflict resolution work? What *really* happens if two of us change the same file? 2D.8 How can I tell who has a module checked out? 2D.9 Where did the .#.1.3 file in my working directory come from? 2D.10 What is this "ignore" business? What is it ignoring? 2D.11 Is there a way to set user-specific configuration options? 2D.12 Is it safe to interrupt CVS using Control-C? 2D.13 How do I turn off the "admin" command? 2D.14 How do I turn off the ability to disable history via "cvs -l"? 2D.15 How do I keep certain people from accessing certain directories? **** Answers: 2D.1 How do I see what CVS is trying to do? The '-t' option on the main "cvs" command will display every external command (mostly RCS commands and file deletions) it executes. When combined with the '-n' option, which prevents the execution of any command that might modify a file, you can see what it will do before you let it fly. The '-t' option will *not* display every internal action, only calls to external programs. To see a harmless example, try typing: cvs -nt update Some systems offer a "trace" or "truss" command that will display all system calls as they happen. This is a *very* low-level interface that does not normally follow the execution of external commands, but it can be useful. The most complete answer is to read the source, compile it with the '-g' option and step through it under a debugger. 2D.2 If I work with multiple modules, should I check them all out and commit them occasionally? Is it OK to leave modules checked out? The simple answers are "Yes." There is no reason to remove working directories, other than to save disk space. As long as you have committed the files you choose to make public, your working directory is just like any other directory. CVS doesn't care whether you leave modules checked out or not. The advantage of leaving them checked out is that you can quickly visit them to make and commit changes. 2D.3 What is a "sticky" tag? What makes it sticky? How do I loosen it? When you execute "update -r ", CVS remembers the . It has become "sticky" in the sense that until you change it or remove it, the tag is remembered and used in references to the file as if you had typed "-r " on the command line. It is most useful for a , which is a sticky tag indicating what branch you are working on. A revision number ("-r ") or date ("-D ") can also become sticky when they are specified on the command line. A sticky tag, revision or date remains until you specify another tag, revision or date the same way. The "update -A" command moves back to the Main branch, which has the side-effect of clearing all sticky items on the updated files. The "checkout" command creates sticky tags, revisions and dates the same way "update" does. Also, the '-k' option records a "sticky" keyword option that is used in further "updates until "update -A" is specified. 2D.4 How do I get an old revision without updating the "sticky tag"? Use the '-p' option to "pipe" data to standard output. The command "update -p -r " sends the selected revision to your standard output (usually the terminal, unless redirected). The '-p' affects no disk files, leaving a "sticky tag" unaltered and avoiding all other side-effects of a normal "update". If you want to save the result, you can redirect "stdout" to a file using your shell's redirection capability. In most shells the following command works: cvs update -p -r filename > diskfile 2D.5 What operations disregard sticky tags? The functions that routinely disregard sticky tags are: 1. Those that work directly on the Repository or its administrative files: admin rtag log status remove history 2. Those that take Tags or revisions as arguments and ignore everything else: (They also never *set* a sticky tag.) rdiff import export 3. The "release" command itself ignores sticky tags, but it calls "cvs -n update" (which *does* pay attention to a sticky tag) to figure out what inconsistencies exist in the working directory. If no discrepancies exist between the files you originally checked out (possibly marked by a sticky tag) and what is there now, "release -d" will delete them all. 4. The "tag" command works on the revision lying in the working directory however it got there. That the revision lying there might happen to have a sticky tag attached to it is not the "tag" command's concern. The main function that *does* read and write sticky tags is the "update" command. You can avoid referring to or changing the sticky tag by using the '-p' option, which sends files to your terminal, touching nothing else. The "checkout" command sets sticky tags when checking out a new module and it acts like "update" when checking out a module into an existing directory. The "diff" and "commit" commands use the sticky tags, unless overridden on the command line. They do not set sticky tags. Note that you can only "commit" to a file checked out with a sticky tag, if the tag identifies a branch. There are really two types of sticky tags, one attached to individual files (in the ./CVS/Entries file) and one attached to each directory (in the ./CVS/Tag file). They can differ. The "add" command registers the desire to add a new file. If the "directory tag" (./CVS/Tag) file exists at the time of the "add", the value stored in ./CVS/Tag becomes the "sticky tag" on the new file. The file doesn't exist in the Repository until you "commit" it, but the ./CVS/Entries file holds the sticky tag name from the time of the "add" forward. 2D.6 Is there a way to avoid reverting my Emacs buffer after committing a file? Is there a "cvs-mode" for Emacs? See Section 4F.1 2D.7 How does conflict resolution work? What *really* happens if two of us change the same file? While editing files, there is no conflict. You are working on separate copies of the file stored in the virtual "branch" represented by your working directories. After one of you commits a file, the other may not commit the same file until "update" has merged the earlier committed changes into the later working file. For example, say you both check out rev 1.2 of and make change to your working files. Your coworker commits revision 1.3. When you try to commit your file, CVS says: cvs commit: Up-to-date check failed for `' You must merge your coworker's changes into your working file by typing: cvs update which will produce the output described in 2B.6. If a conflict occurs, the filename will be shown with a status of 'C'. After you resolve any overlaps caused by the merging process, you may then commit the file. See 3P.6 for info on "sticky conflicts". Even if you get a simple 'M', you should examine the differences before committing the file. A smooth, error-free text merge is still no indication that the file is in proper shape. Compile and test it at least. The answer to two obvious questions is "Yes". Yes, the first one who commits avoids the merge. Later developers have to merge the earlier changes into their working files before committing the merged result. Depending on how difficult the merge is and how important the contending projects are, the order of commits and updates might have to be carefully staged. And yes, between the time you execute "update" and "commit" (while you are fixing conflicts and testing the results) someone else may commit another revision of . You will have to execute "update" again to merge the new work before committing. Most organizations don't have this problem. If you do, you might consider splitting the file. Or hiring a manager. 2D.8 How can I tell who has a module checked out? If you "checkout" module names (not relative pathnames) and you use the release command, the "history" command will display active checkouts, who has them and where they were checked out. It is advisory only; it can be circumvented by using the '-l' option on the main "cvs" command. 2D.9 Where did the .#.1.3 file in my working directory come from? It was created during an "update" when CVS merged changes from the Repository into your modified working file. It serves the same purpose as any "backup" file: saving your bacon often enough to be worth retaining. It is invaluable in recovering when things go wrong. Say Developers A (you) and B check out rev 1.3 of file . You both make changes -- different changes. B commits first, so ,v in the Repository contains revisions up through 1.4. At this point, there are 5 (yes, five) versions of the file of interest to you: 1. Revision 1.3 (What you originally checked out.) 2. Revision 1.4 (What you need from developer B.) 3. Your old working file. (Before the update.) 4. Your new working file. (After the merge caused by "update".) 5. Revision 1.5 (Which you will commit shortly.) In the case where your working file was not modified, #1 and #3 will be the same, as will #2 and #4. In this degenerate case, there is no need to create #5. The following assumes that your working file was modified. If the merge executed by the "update" caused no overlaps, and you commit the file immediately, #4 and #5 will be the same. But you can make arbitrary changes before committing, so the difference between #4 and #5 might be more than just the correction of overlaps. In general, though, you don't need #4 after a commit. But #3 (which is the one saved as ".#.1.3") holds all of your work, independent of B's work. It could represent a major effort that you couldn't afford to lose. If you don't save it somewhere, the merge makes #3 *disappear* under a potential blizzard of conflicts caused by overlapping changes. I have been saved a few times, and others I support have been saved hundreds of times, by the ability to "diff ", which can be done in the example above by the Unix shell command: cvs update -p -r 1.3 | diff - .#.1.3 The assumption is that the ".#" files will be useful far beyond the "commit" point, but not forever. You are expected to run the "normal" Unix cleanup script from "cron", which removes "#*" and ".#*" files older than a some period chosen by your sysadmin, usually ranging from 7 to 30 days. A question was raised about the need for #3 after #5 has been committed, under the assumption that you won't commit files until everything is exactly as you like them. This assumes perfect humans, which violates one of the Cardinal rules of Software Engineering: Never assume any form of discipline on the part of the users of software. If restrictions are not bound into the software, then you, the toolsmith, have to arrange a recovery path. In other words, I've seen every possible variety of screwup you can imagine in #5. There is no way to make assumptions about what "should" happen. I've seen #5 filled with zeros because of NFS failures, I've seen emacs core dumps that leave #5 in an unreasonable state, I've seen a foolish developer uppercase the whole file (with his "undo" size set low so he couldn't undo it) and decide that it would be less work to play with the uppercased file than to blow it away and start over. I've even seen committed files with conflict markers still in them, a sure sign of carelessness. There are all sorts of scenarios where having #3 is incredibly useful. You can move it back into place and try again. 2D.10 What is this "ignore" business? What is it ignoring? The "update" and "import" commands use collections of Unix wildcards to skip over files and directories matching any of those patterns. You may add to the built-in ignore list by adding lines of whitespace-separated wildcards to the following places: (They are read in this order.) 1. In a file named "cvsignore" in $CVSROOT/CVSROOT. A Repository Administrator uses this to add site-specific files and patterns to the built-in ignore list. 2. In a file named ".cvsignore" in your home directory. For user-specific files. For example, if you use "__" as your default junk file prefix, you can put "__*" in your .cvsignore file. People who play around exclusively in directory trees where the Makefiles are generated by "imake" or "configure" might want to put "Makefile" in their ignore list, since they are all generated and usually don't end up in the Repository. 3. In the CVSIGNORE environment variable. For session-specific files. 4. Via the '-I' option on "import" or "update" commands. For this-command-only files. 5. In a file named ".cvsignore" within each directory. The contents of a ".cvsignore" file in each directory is temporarily added to the ignore list. This way you can ignore files that are peculiar to that directory, such as executables and other generated files without known wildcard patterns. In any of the places listed above, a single '!' character nulls out the ignore list. A Repository administrator can use this to override, rather than enhance, the built-in ignore list. A user can choose to override the system-wide ignore list. For example, if you place "! *.o *.a" in your .cvsignore file, only *.o *.a files, plus any files a local-directory .cvsignore file, are ignored. A variant of the ignore-file scheme is used internally during checkout. "Module names" found in the modules file (or on the "checkout" command line) that begin with a '!' are ignored during checkout. This is useful to permanently ignore (if the '!' path is in the modules file) or temporarily ignore (if the '!' path is on the command line) a sub-directory within a Repository hierarchy. For example: cvs checkout !gnu/emacs/tests gnu/emacs would checkout the module (or relative path within $CVSROOT) named "gnu/emacs", but ignore the "tests" directory within it. 2D.11 Is there a way to set user-specific configuration options? User-specific configuration is available through use of a ".cvsrc" file in your home directory. CVS searches the first column of your ~/.cvsrc file for the cvs command name you invoked. If the command is found, the rest of the line is treated like a set of command line options, stuffed into the command line before the arguments you actually typed. For example, if you always want to see context diffs and you never want to have to delete a file before you run "cvs remove", then you should create a .cvsrc file containing the following: diff -c remove -f which will add the given options to every invocation of the given commands. [[The rest of this will be removed someday, when CVS changes.]] I would like to stop here with a comment that the command name to use is the full, canonical one. But the command that the cvsrc support uses is the string you typed on the command line, not the proper command. So to get the full effect of the above example, you should also add all the alternate command names: di -c dif -c rm -f delete -f There are two other limitations that will probably be fixed when CVS sprouts long option names: 1. It only affects options made available on the command line. There is a limited number of short options. With long option names, there is no problem. You can have as many long options as you like, affecting anything that looks malleable. 2. The existing command line options do not come in on/off pairs, so there is no easy way to override your ~/.cvsrc configuration for a single invocation of a command. Choosing a good set of long option pairs would fix this. 2D.12 Is it safe to interrupt CVS using Control-C? It depends on what you mean by "safe". ("Ah," said Arthur, "this is obviously some strange usage of the word *safe* that I wasn't previously aware of." -- Hitchhiker's Guide to the Galaxy) You won't hurt the underlying RCS files and if you are executing a command that only *reads* data, you will have no cleanup to do. But you may have to hit Control-C repeatedly to stop it. CVS uses the Unix "system" routine which blocks signals in the CVS parent process. A single Control-C during "system" will only halt the child process, usually some form of RCS command. If you don't hit another Control-C while the CVS process has control, it is likely to continue onto the next task assuming that the earlier one did its job. It is not enough to hit two Control-C's. You might simply kill two child processes and not interrupt CVS at all. Depending on the speed of your processor, your terminal and your fingers, you might have to hit dozens of Control-C's to stop the damn thing. Executing a CVS command, such as "commit" or "tag" that writes to the files is a different matter. Since CVS is not a full-fledged database, with what database people call "commit points", merely stopping the process will not back out the "transaction" and place you back in the starting blocks. CVS has no concept of an "atomic" transaction or of "backtracking", which means that a command can be half-executed. Hitting Control-C will usually leave lock files that you have to go clean up in the Repository. Example1: If you interrupt a multi-file "commit" in the middle of an RCS checkin, RCS will leave the file either fully checked-in or in its original state. But CVS might have been half-way through the list of files to commit. The directory or module will be inconsistent. To recover, you must remove the lock files, then decide whether you want to back out or finish the job. To back out, you'll have to apply the "admin -o" command, very carefully, to remove the newly committed revisions. This is usually a bad idea, but is occasionally necessary. To finish, you can simply retype the same commit command. CVS will figure out what files are still modified and commit them. It helps that RCS doesn't leave a file in an intermediate state. Example2: If you interrupt a multi-file "tag" command, you have a problem similar, but not equivalent, to interrupting a "commit". The RCS file will still be consistent, but unlike "commit", which only *adds* to the RCS file, "tag" can *move* a tag and it doesn't keep a history of what revision a tag used to be attached to. Normally, you have little choice but to re-execute the command and allow it to tag everything consistently. You might be able to recover by carefully re-applying the tags via the "cvs admin -N" command, but you'll still have to dig up from outside sources the information you use to determine what tag was on what revision in what file. the Repository, or by using the equivalent: "cvs admin". Halting a new "checkout" should cause no harm. If you don't want it, "release" (or rm -rf) it. If you do want it, re-execute the command. A repeated "checkout" from above a directory acts like a repeated "update -d" within it. Halting "update" half-way will give you an unpredictable collection of files and revisions. To continue, you can rerun the update and it should move you forward into in a known state. To back out, you'll have to examine the output from the first "update" command, take a look at each file that was modified and reconstruct the previous state by editing the ./CVS/Entries file and by using "cvs admin". Good Luck. 2D.13 How do I turn off the "admin" command? In the current revision, you'd have to edit the source code. 2D.14 How do I turn off the ability to disable history via "cvs -l"? In the current revision, you'd have to edit the source code. 2D.15 How do I keep certain people from accessing certain directories? If you don't try to run CVS set[ug]id, you can use Unix groups and permissions to limit access to the Repository. If you only want to limit "commit" commands, you can write a program to put in the "commitinfo" file. In the "contrib" directory, there are a few scripts that might help you out. ======================================== == Section 3 ==== Commands ==== ======================================== This section contains questions that are easily recognized to be about a single command, usually of the form: "Why does the 'xyz' command do this?" Questions about "missing" features and side-effects not attributable to a particular command are in Section 2D, "General Questions". I won't provide patches here that are longer than a few lines. Patches referred to in this section are available in the FTP archive described toward the beginning of this document. ---------------- -- Section 3A -- "add", "ad", "new" ---------------- **** Questions: 3A.1 What is "add" for? 3A.2 How do I add a new file to the branch I'm working on? 3A.3 Why did my new file end up in the Attic? 3A.4 Now that it's in the Attic, how do I connect it to the Main branch? 3A.5 How do I avoid the hassle of reconnecting an Attic-only file to the Main Branch? 3A.6 How do I cancel an "add"? 3A.7 What are the ./CVS/file,p and ./CVS/file,t files for? 3A.8 How do I "add" a binary file? **** Answers: 3A.1 What is "add" for? To add a new directory to the Repository or to register the desire to add a new file to the Repository. The directory is created immediately, while the desire to add the file is recorded in the local ./CVS administrative directory. To really add the file to the Repository, you must then "commit" it. 3A.2 How do I add a new file to the branch I'm working on? The user actions for adding a file to any branch, including the Main Branch, are exactly the same. You are in a directory checked out (or updated) with the '-A' option (to place you on the Main Branch) or the "-r " option (to place you on a branch tagged with ). To add to the branch you are on, you type: cvs add cvs commit If no ./CVS/Tag file exists (the '-A' option deletes it), the file will be added to the Main Branch. If a ./CVS/Tag file exists (the "-r " option creates it), the file will be added to the branch named (i.e. tagged with) . Unless you took steps to first add the file to the Main Branch, your new file ends up in the Attic. 3A.3 Why did my new file end up in the Attic? The file is thrown into the Attic to keep it from being visible when you check out the Main Branch, since it was never committed to the Main Branch. 3A.4 Now that it's in the Attic, how do I connect it to the Main branch? That can be considered a kind of "merge". See 4C.8 3A.5 How do I avoid the hassle of reconnecting an Attic-only file to the Main Branch? You create it on the Main Branch first, then branch it. If you haven't yet added the file or if you decided to delete the new Attic file and start over, then do the following: (If you added the file (or worse, the 157 files) to the Attic and don't want to start over, try the procedure in 4C.8.) 1. Temporarily remove the sticky branch information. Either: A. Move the whole directory back to the Main Branch. [This might not be a good idea if you have modified files, since it will require a merge in each direction.] cvs update -A *or* B. Move the ./CVS/Tag file out of the way. mv ./CVS/Tag HOLD_Tag 2. Add and branch the file "normally": cvs add cvs commit cvs tag -b [ is the same Branch Tag as you used on all the other files. Look at ./CVS/Entries or the output from "cvs stat" for sticky tags.] 3. Clean up the temporary step. A. If you moved the ./CVS/Tag file, put it back. Then move the new file onto the branch where you are working. mv HOLD_Tag ./CVS/Tag cvs update -r B. If you ran "update -A" rather than moving the ./CVS/Tag file, move the whole directory (including the new file) back onto the branch where you were working: cvs update -r 3A.6 How do I cancel an "add"? If you want to remove the file entirely and cancel the "add" at the same time, type: cvs remove -f If you want to cancel the "add", but leave the file as it was before you typed "cvs add", then you have to fake it: mv .hold cvs remove mv .hold 3A.7 What are the ./CVS/file,p and ./CVS/file,t files for? The ./CVS/file,p and ./CVS/file,t files are created by the "add" command to hold command line options and message text between the time of the "add" command and the expected "commit". The ./CVS/file,p file is always null, since its function was absorbed by the "options" field in the ./CVS/Entries file. If you put something in this file it will be used as arguments to the RCS "ci" command that commit uses to check the file in, but CVS itself doesn't put anything there. The ./CVS/file,t file is null unless you specify an initial message in an "add -m 'message'" command. The text is handed to "rcs -i -t./CVS/file,t" to create the initial RCS file container. Both files must exist to commit a newly added file. If the ./CVS/file,p file doesn't exist, CVS prints an error and aborts the commit. If the ./CVS/file,t file doesn't exist, RCS prints an error and CVS gets confused, but does no harm. To recover from missing ,p and ,t files, just create two zero-length files and rerun the "commit". 3A.8 How do I "add" a binary file? If you configured CVS to use the GNU version of "diff" and "diff3", you only need to turn off RCS keyword expansion. First you turn off RCS keyword expansion for the initial checkin by using "add -ko". It works like "update -ko" in creating a "sticky" option only for the copy of the file in the current working directory. cvs add -ko Commit the file normally. The sticky -ko option will be used. cvs commit Then mark the RCS file in the Repository so that keyword expansion is turned off for all checked out versions of the file. cvs admin -ko Since "admin -ko" records the keyword substitution value in the Repository's RCS file, you no longer need the sticky option. You can turn it off with the "update -A" command, but if you were on a branch, you'll have to follow it "update -r " to put yourself back on the branch. Managing that binary file is another problem. See 4D.1. ---------------- -- Section 3B -- "admin", "adm", "rcs" ---------------- **** Questions: 3B.1 What is "admin" for? 3B.2 Wow! Isn't that dangerous? 3B.3 What would I normally use "admin" for? 3B.4 What should I avoid when using "admin"? 3B.5 How do I restrict the "admin" command? The -i flag in the modules file can restrict commits. What's the equivalent for "admin"? 3B.6 I backed out a revision with "admin -o" and committed a replacement. Why doesn't "update" retrieve the new revision? **** Answers: 3B.1 What is "admin" for? To provide direct access to the underlying "rcs" command (which is not documented in this FAQ) bypassing all safeguards and CVS assumptions. 3B.2 Wow! Isn't that dangerous? Yes. Though you can't hurt the internal structure of an RCS file using its own "rcs" command, you *can* change the underlying RCS files using "admin" in ways that CVS can't handle. If you feel the need to use "admin", create some test files with the RCS "ci" command and experiment on them with "rcs" before blasting any CVS files. 3B.3 What would I normally use "admin" for? Normally, you wouldn't use admin at all. In unusual circumstances, experts can use it to set up or restore the internal RCS state that CVS requires. You can use "admin -o" (for "outdate") to remove revisions you don't care about. This has its own problems, such as leaving dangling Tags and confusing the "update" command. There is some feeling among manipulators of binary files that "admin -l" should be used to serialize access. See 3C.8. An interesting use for "admin" came up while maintaining CVS itself. I import versions of CVS onto the Vendor branch of my copy of CVS, make changes to some files and ship the diffs (created by "cvs diff -c -r TO_BRIAN") off to Brian Berliner. After creating the diff, I retag ("cvs tag -F TO_BRIAN") the working directory, which is then ready to produce the next patch. I'll use "add.c" as an example (only because the name is short). When the next release came out, I discovered that the released "add.c" (version 1.1.1.3 on the Vendor branch) was exactly the same as my modified file (version 1.3). I didn't care about the changelog on versions 1.2 and 1.3 (or the evidence of having done the work), so I decided to revert the file to the state where it looked like I had not touched the file -- where I was just using the latest on the vendor branch after a sequence of imports. To do that, I removed all the revisions on the main branch, except for the original 1.1 from which the Vendor branch sprouts: cvs admin -o1.2: add.c Then I set the RCS "default branch" back to the Vendor branch, the way import would have created it: cvs admin -b1.1.1 add.c And I moved the "TO_BRIAN" Tag to the latest revision on the Vendor branch, since that is the base from which further patches would be created (if I made any): cvs admin -NTO_BRIAN:1.1.1.3 add.c Instead of 1.1.1.3, I could have used one of the "Release Tags" last applied by "import" (3rd through Nth arguments). Suggestion: Practice on non-essential files. 3B.4 What should I avoid when using "admin"? If you know exactly what you are doing, hack away. But under normal circumstances: Never use "admin" to alter branches (using the '-b' option), which CVS takes very seriously. If you change the default branch, CVS will not work as expected. If you create new branches without using the "tag -b" command, you may not be able to treat them as CVS branches. See 3C.8 for a short discussion of how to use "admin -l" for serializing access to binary files. The "admin -o " allows you to delete revisions, usually a bad idea. You should commit a correction rather than back out a revision. Outdating a revision is prone to all sorts of problems: 1. Discarding data is always a bad idea. Unless something in the revision you just committed is a threat to your job or your life, (like naming a function "_is_a_dweeb", or including the combination to the local Mafioso's safe in a C comment), just leave it there. No one cares about simple mistakes -- just commit a corrected revision. 2. The time travel paradoxes you can cause by changing history are not worth the trouble. Even if CVS can't interfere with your parents' introduction, it *can* log commits in at least two ways (history and loginfo). The reports now lie -- the revision referred to in the logs no longer exists. 3. If you used "import" to place into CVS, outdating all the revisions on the Main branch back to and including revision 1.2 (or worse, 1.1), will produce an invalid CVS file. If the ,v file only contains revision 1.1 (and the connected branch revision 1.1.1.1), then the default branch must be set to the Vendor branch as it was when you first imported the file. Outdating back through 1.2 doesn't restore the branch setting. Despite the above admonition against it, "admin -b" is the only way to recover: cvs admin -b1.1.1 4. Although you can't outdate a physical (RCS) branch point without removing the whole branch, you *can* outdate a revision referred to by a magic branch tag. If you do so, you will invalidate the branch. 5. If you "outdate" a tagged revision, you will invalidate all uses of the , not just the one on . A tag is supposed to be attached to a consistent set of files, usually a set built as a unit. By discarding one of the files in the set, you have destroyed the utility of the . And it leaves a dangling tag, which points to nothing. 6. And even worse, if you commit a revision already tagged, you will alter what the pointed to without using the "tag" command. For example, if revision 1.3 has attached to it and you "outdate" the 1.3 revision, will point to a nonexistent revision. Although this is annoying, it is nowhere near as much trouble as the problem that will occur when you commit to this file again, recreating revision 1.3. The old tag will point to the new revision, a file that was not in existence when the was applied. And the discrepancy is nearly undetectable. If you don't understand the above, you should not use the admin command at all. 3B.5 How do I restrict the "admin" command? The -i flag in the modules file can restrict commits. What's the equivalent for "admin"? At this writing, to disable the "admin" command, you will have to change the program source code, recompile and reinstall. 3B.6 I backed out a revision with "admin -o" and committed a replacement. Why doesn't "update" retrieve the new revision? CVS is confused because the revision in the ./CVS/Entries file matches the latest revision in the Repository *and* the timestamp in the ./CVS/Entries file matches your working file. CVS believes that your file is "up-to-date" and doesn't need to be updated. You can cause CVS to notice the change by "touch"ing the file. Unfortunately what CVS will tell you is that you have a "Modified" file. If you then "commit" the file, you will bypass the normal CVS check for "up-to-date" and will probably commit the revision that was originally removed by "admin -o". Changing a file without changing the revision number confuses CVS no matter whether you did it by replacing the revision (using "admin -o" and "commit" or raw RCS commands) or by applying an editor directly to a Repository (",v") file. Don't do it unless you are absolutely certain no one has the latest revision of the file checked out. The best solution to this is to institute a program of deterrent flogging of abusers of "admin -o". The "admin" command has other problems." See 3B.4 above. ---------------- -- Section 3C -- "checkout", "co", "get" ---------------- **** Questions: 3C.1 What is "checkout" for? 3C.2 What is the "module" that "checkout" takes on the command line? 3C.3 Isn't a CVS "checkout" just a bunch of RCS checkouts? 3C.4 What's the difference between "update" and "checkout"? 3C.5 Why can't I check out a file from within my working directory? 3C.6 How do I avoid dealing with those long relative pathnames? 3C.7 Can I move a checked-out directory? Does CVS remember where it was checked out? 3C.8 How can I lock files while I'm working on them the way RCS does? 3C.9 What is "checkout -s"? How is it different from "checkout -c"? **** Answers: 3C.1 What is "checkout" for? To acquire a copy of a module (or set of files) to work on. All work on files controlled by CVS starts with a "checkout". 3C.2 What is the "module" that "checkout" takes on the command line? It is a name for a directory or a collection of files in the Repository. It provides a compact name space and the ability to execute before and after helper functions based on definitions in the modules file. See 1D.11. 3C.3 Isn't a CVS "checkout" just a bunch of RCS checkouts? Like much of CVS, a similar RCS concept is used to support a CVS function. But a CVS checkout is *not* the same as an RCS checkout. Differences include: 1. CVS does not lock the files. Others may access them at the same time. 2. CVS works best when you provide a name for a collection of files (a module or a directory) rather than an explicit list of files to work on. 3. CVS remembers what revisions you checked out and what branch you are on, simplifying later commands. 3C.4 What's the difference between "update" and "checkout"? The "checkout" and "update" commands are nearly equivalent in how they treat individual files. They differ in the following ways: 1. The "checkout" command always creates a directory, moves into it, then becomes equivalent to "update -d". 2. The "update" command does not create directories unless you add the '-d' option. 3. "Update" is intended to be executed within a working directory created by "checkout". It doesn't take a module or directory argument, but figures out what Repository files to look at by reading the files in the ./CVS administrative directory. 4. The two commands generate completely different types of records in the "history" file. 3C.5 Why can't I check out a file from within my working directory? Though you *can* check out a file, you normally check out a module or directory. And you normally do it only once at the beginning of a project. After the initial "checkout", you can use the "update" command to retrieve any file you want within the checked-out directory. There is no need for further "checkout" commands. If you want to retrieve another module or directory to work on, you must provide two pathnames: where to find it in the Repository and where to put it on disk. The "modules" file and your current directory supply two pieces of naming information. While inside a checked-out working directory, the CVS administrative information provides most of the rest. You should be careful not to confuse CVS with RCS and use "checkout" in the RCS sense. An RCS "checkout" (which is performed by the RCS "co" command) is closer to a "cvs update" than to a "cvs checkout". 3C.6 How do I avoid dealing with those long relative pathnames? This question has also been phrased: How do I avoid all those layers of directories on checkout? or Why do I have to go to the top of my working directory and checkout some long pathname to get a file or two? This type of question occurs only among groups of people who decide not to use "modules". The answer is to use "modules". When you hand the "checkout" command a relative pathname rather than a module name, all directories in the path are created, maintaining the same directory hierarchy as in the Repository. The same kind of environment results if you specify a "module" that is really an alias expanding into a list of relative pathnames rather than a list of module names. If you use "module" names, "checkout" creates a single directory by the name of the module in your current directory. This "module" directory becomes your working directory. The "module" concept combines the ability to "name" a collection of files with the ability to structure the Repository so that consistent sets of files are checked out together. It is the responsibility of the Repository Administrators to set up a modules file that describes the software within the Repository. 3C.7 Can I move a checked-out directory? Does CVS remember where it was checked out? Yes and Yes. The ./CVS/Repository file in each working directory contains a pathname pointing to the matching directory within the Repository. The pathname is either absolute or relative to $CVSROOT, depending on how you configured CVS. When you move a checked-out directory, the CVS administrative files will move along with it. As long as you don't move the Repository itself, or alter your $CVSROOT variable, the moved directory will continue to be usable. CVS remembers where you checked out the directory in the "history" file, which can be edited, or even ignored if you don't use the "working directory" information displayed by the "history" command. 3C.8 How can I lock files while I'm working on them the way RCS does? Until the day arrives of the all-powerful merge tool, there are still files that must be accessed serially. For those instances, here's a potential solution: 1. Install a pre-commit program in the "commitinfo" file to check for RCS locks. The program "rcslock.pl" performs this function. It can be found in the contrib directory of the CVS source distribution. 2. When you want to make a change to a file you know can't be merged, first use "cvs admin -l" to lock the file. If you can't acquire the lock, use the standard "locked out" protocol: go talk to the person holding the lock. 3. Make sure the pre-commit program prints a message and exits with a non-zero status if someone besides the user running "commit" has the file locked. This non-zero exist status will cause the "commit" to fail cleanly. 4. Make sure the pre-commit program exits with a zero status if the file is either unlocked or locked by the user running "commit". The "cvs commit" command that kicked off the pre-commit program will take a zero exist status as an OK and checkin the file, which has the side-effect of unlocking it. ===> The following is opinion and context. Don't read it if you are looking for a quick fix. The topic of locking CVS files resurfaces on the network every so often, producing the same results each time: The Big Endians: CVS was designed to avoid locks, using a copy-modify-merge model. Locking is not necessary and you should take the time to learn the CVS model which many people find workable. So why not get with the program and learn how to think the CVS way? The Little Endians: The users determine how a tool is to be used, not the designers. We, the users, have always used locking, our bosses demand locking, locking is good, locking is God. I don't want to hear any more lectures on the CVS model. Make locking work. Any organization making active changes to a source base will eventually face the need to do parallel development. Parallel development implies merges. (If you plan to keep separate copies of everything and never merge, good luck. Tell me who you work for so I can buy stock in your disk suppliers this year and sell your stock short next year.) Merges will never go away. CVS chose to make "merges" stand front and center as an important, common occurrence in development. It is one way of looking at things. For free-format text, the merge paradigm gives you a considerable amount of freedom. It does take a bit of management, but any project should be ready to deal with it. On the other hand, there are many files that can't be merged using text merge techniques. Straight text merge programs like "diff3" are guaranteed to fail on executables (with relative branch statements), files with self-referential counts stored in the file (such as TAGS files), or files with relative motion statements in them (such as Frame MIF files, many postscript files). They aren't all binary files. For these types of files, and many others, there are only two solutions: 1. Complex merge tools that are intimately aware of the contents of the files to be merged. (ClearCase, and probably others, allow you to define your own "files types" with associated "merge tools".) 2. Serialization of access to the file. The only technical solution to the problem of serialization is "locking". Since you can call a program that offers: "Which one do you want? A/B?" a "merge tool", more and more merge tools will appear which can be hooked into a merge-intensive program like CVS. Think of a bitmap "merge" tool that displays the bitmaps on the screen and offers a "paint" interface to allow you to cut and paste, overlay, invert or fuse the two images such that the result is a "merged" file. My conclusion is that the need for locking is temporary, awaiting better technology. For large development groups, locking is not an alternative to merging for text files. 3C.9 What is "checkout -s"? How is it different from "checkout -c"? The '-c' and '-s' options to "checkout" both cause the modules file to appear on standard output, but formatted differently. "checkout -c" lists the modules file alphabetized by the module name. It also prints all data (including options like '-a' and "-o ") specified in the modules file. "checkout -s" lists the modules file sorted by "status" field, then by module name. The status field was intended to allow you to mark modules with strings of your choice to get a quick sorted report based on the data you chose to put in the status fields. I have used it for priority ("Showstopper", etc as tied into a bug database), for porting status ("Ported", "Compiled", etc. when porting a large collection of modules), for "assignee" (the person responsible for maintenance), and for "test suite" (which automatic test procedure to run for a particular module). ---------------- -- Section 3D -- "commit", "ci", "com" ---------------- **** Questions: 3D.1 What is "commit" for? 3D.2 If I edit ten files, do I have to type "commit" ten times? 3D.3 Explain: cvs commit: Up-to-date check failed for `' 3D.4 What happens if two people try to "commit" conflicting changes? 3D.5 I committed something and I don't like it. How do I remove it? 3D.6 Explain: cvs commit: sticky tag `V3' for file `X' is not a branch 3D.7 Why does "commit -r " put newly added files in the Attic? 3D.8 Why would a "commit" of a newly added file not produce rev 1.1? **** Answers: 3D.1 What is "commit" for? To store new revisions in the Repository, making them visible to other users. 3D.2 If I edit ten files, do I have to type "commit" ten times? No. The "commit" command will take multiple filenames, directory names and relative pathnames on the command line and commit them all with the same log message. If a file is unchanged, even if it is explicitly listed on the command line, CVS will skip it. Like all CVS commands, "commit" will work on the whole directory by default. Just type "cvs commit" to tell CVS to commit all modified files (i.e. the files that "update" would display preceded by 'M') in the current directory and in all sub-directories. 3D.3 Explain: cvs commit: Up-to-date check failed for `' You may not "commit" a file if your BASE revision (i.e. the revision you last checked out, committed or retrieved via "update") doesn't match the HEAD revision (i.e the latest revision on your branch, usually the Main Branch). In other words, someone committed a revision since you last executed "checkout", "update" or "commit". You must now execute "update" to merge the other person's changes into your working file before "commit" will work. You are thus protected (somewhat) from a common form of race condition in source control systems, where a checkin of a minor alteration of a second copy of the same base file obliterates the changes made in the first. Normally, the "update" command's auto-merge should be followed by another round of building and testing before the "commit". 3D.4 What happens if two people try to "commit" conflicting changes? Conflicts can occur only when two developers check out the same revision of the same file and make changes. The first developer to commit the file has no chance of seeing the conflict. Only the second developer runs into it, usually when faced with the "Up-to-date" error explained in the previous question. There are two types of conflicts: 1. When two developers make changes to the same section of code, the auto-merge caused by "update" will print a 'C' on your terminal and leave "overlap" markers in the file. You are expected to examine and clean them up before committing the file. (That may be obvious to *some* of you, but . . .) 2. A more difficult problem arises when two developers change different sections of code, but make calls to, or somehow depend on, the old version of each other's code. The auto-merge does the "right" thing, if you view the file as a series of text lines. But as a program, the two developers have created a problem for themselves. This is no different from making cross-referential changes in *separate* files. CVS can't help you. In a perfect world, you would each refer to the specification and resolve it independently. In the real world you have to talk/argue, read code, test and debug until the combined changes work again. Welcome to the world of parallel development. 3D.5 I committed something and I don't like it. How do I remove it? Though you *can* use the "admin -o" (synonym: "rcs -o") command to delete revisions, unless the file you committed is so embarrassing that the need to eradicate it overrides the need to be careful, you should just grab an old version of the file ("update -p -r " might help here) and commit it on top of the offending revision. See Section 3B on "admin". 3D.6 Explain: cvs commit: sticky tag `V3' for file `X' is not a branch The message implies two things: 1. You created your working directory by using "checkout -r V3", or you recently executed "update -r V3". 2. The tag named V3 is not a branch tag. CVS records (i.e. makes "sticky") any "-r " argument handed to the "checkout" or "update" commands. The is recorded as the CVS working branch, which is the branch to which "commit" will add a new revision. Branch tags are created when you use the -b switch on the "tag" or "rtag" commands. Branch tags are magic tags that don't create a physical branch, but merely mark the revision to branch from when the branch is needed. The first commit to a magic branch creates a physical branch in the RCS files. You can commit onto the end of the Main Trunk, if you have no sticky tag at all, or onto the end of a branch, if you have a sticky branch tag. But you can't commit a file that has a sticky tag not pointing to a branch. CVS assumes a sticky Tag or Revision that does not refer to a branch is attached to the middle of a series of revisions. You can't squeeze a new revision between two others. Sticky dates also block commits since they never refer to a branch. Scenario1: If you don't want a branch and were just looking at an old revision, then you can move back to the Main Branch by typing: cvs update -A {files or dirs, default is '.'} or you can move to the branch named by: cvs update -r {files or dirs, default is '.'} Scenario2: If you really wanted to be on a branch and made an earlier mistake by tagging your branch point with a non-branch tag, you can recover by adding a new branch tag to the old non-branch tag: cvs rtag -b -r (It was not a big mistake. Branch-point tags can be useful. But the must have a different name.) If you don't know the name or don't use "modules", you can also use "tag" this way: cvs update -r cvs tag -b . Then, to put your working directory onto the branch, you type: cvs update -r You can't delete before adding , and I would not advise deleting the at all, because it is useful in referring to the branch point. If you must, you can delete the non-branch tag by: cvs rtag -d or cvs tag -d . Scenario3: If you made the same mistake as in Scenario2 (of placing a non-branch tag where you wanted a branch tag), but really want to be the name of your branch, you can execute a slightly different series of commands to rename it and move your working directory onto the branch. Warning: This is not a way to rename a branch tag. It is a way to turn a non-branch tag into a branch tag with the same name. cvs rtag -r cvs rtag -d cvs rtag -b -r Then, if you really must, delete the : cvs rtag -d Note: The unwieldy mixture of "tag" and "rtag" is mostly because you can't specify a revision (-r ) to the "tag" command. See 4C.3 for more info on creating a branch. 3D.7 Why does "commit -r " put newly added files in the Attic? If you specify "-r " (where is a dotted numeric number like 2.4), it correctly sets the initial revision to , but it also attaches the numeric as a sticky tag and throws the file into the Attic. This is a bug. The obvious solution is to move the file out of the Attic into the associated Repository directory and "update -A" the file. There are no Tags to clean up. If you specify "-r " to commit a newly added file, the is treated like a , which becomes a symbolic RCS label pointing to the string '1', which can be considered to be the "Main branch number" when the main branch is still at revision 1.N. The file is also thrown into the Attic. See 4C.8 for a way to recover from this. In fact, a plain "commit" without the "-r" will throw a newly added file into the Attic if you added it to a directory checked out on a branch. See 3A.[2-5]. See Section 4C, on Branching, for many more details. 3D.8 Why would a "commit" of a newly added file not produce rev 1.1? When committing a newly added file CVS looks for the highest main branch major number in all files in the ./CVS/Entries file. Normally it is '1', but if you have a file of revision 3.27 in your directory, CVS will find the '3' and create revision 3.1 for the first rev of . Normally, the first revision is 1.1. ---------------- -- Section 3E -- "diff", "di", "dif" ---------------- **** Questions: 3E.1 What is "diff" for? 3E.2 Why did "diff" display nothing when I know there are later committed revisions in the Repository? 3E.3 How do I display what changed in the Repository since I last executed "checkout", "update" or "commit"? 3E.4 How do I display the difference between my working file and what I checked in last Thursday? 3E.5 Why can't I pass long options, like --unified, to "diff"? **** Answers: 3E.1 What is "diff" for? 1. To display the difference between a working file and its BASE revision (the revision last checked out, updated or committed): cvs diff 2. To display the difference between a working file and a committed revision of the same file: cvs diff -r 3. To display the difference between two committed revisions of the same file: cvs diff -r -r You can specify any number of arguments. Without any arguments, it compares the whole directory. In the examples above, "-D " may be substituted wherever "-r " appears. The revision a refers to is the revision that existed on that date. 3E.2 Why did "diff" display nothing when I know there are later committed revisions in the Repository? By default, "diff" displays the difference between your working file and the BASE revision. If you haven't made any changes to the file since your last "checkout", "update" or "commit" there is no difference to display. To display the difference between your working file and the latest revision committed to your current branch, type: cvs diff -r HEAD 3E.3 How do I display what changed in the Repository since I last executed "checkout", "update" or "commit"? A special tag (interpreted by CVS -- it does not appear in the Tag list) named "BASE" always refers to the revision you last checked out, updated or committed. Another special tag named "HEAD" always refers to the latest revision on your working branch. To compare BASE and HEAD, you type: cvs diff -r BASE -r HEAD 3E.4 How do I display the difference between my working file and what I checked in last Thursday? cvs diff -D "last Thursday" where "last Thursday" is a date string. To be more precise, the argument to the '-D' option is a timestamp. Many formats are accepted. See the man page under "-D date_spec" for details. 3E.5 Why can't I pass long options, like --unified, to "diff"? CVS only handles single character '-X' arguments, not the FSF long options. CVS also passes through only arguments it knows about, because a few arguments are captured and interpreted by CVS. If you didn't configure RCS and CVS to use the GNU version of diff, long options wouldn't work even if future versions of CVS acquire the ability to pass them through. Most of the long options have equivalent single-character options, which do work. The "--unified" option is equivalent to '-u' in revisions of GNU diff since 1.15. ---------------- -- Section 3F -- "export", "exp", "ex" ---------------- **** Questions: 3F.1 What is "export" for? 3F.2 Why does it remove the RCS keywords so I can't use the "ident" command on the source files? 3F.3 Can I override the '-kv' flag CVS passes to RCS? 3F.4 Why doesn't "export" have a '-k' flag like "import" does? 3F.5 Why does "export -D" check out every file in the Attic? **** Answers: 3F.1 What is "export" for? "export" checks out a copy of a module in a form intended for export outside the CVS environment. The "export" command produces the same directory and file structure as the "checkout" command, but it doesn't create "CVS" sub-directories and it removes all the RCS keywords from the files. 3F.2 Why does it remove the RCS keywords so I can't use the "ident" command on the source files? It removes the RCS keywords, so that if the recipient of the exported sources checks them into another set of RCS files (with or without CVS), and then makes modifications through RCS or CVS commands, the revision numbers that they had when you exported them will be preserved. (That ident no longer works is just an unfortunate side effect.) The theory is that you are exporting the sources to someone else who will make independent changes, and at some point you or they will want to know