|< Day Day Up >|
When you work on a project involving many files that evolve over long periods of time, it can be difficult to keep track of the different versions of the files, particularly if several people are updating the files. This problem frequently occurs in large software development projects. Source code and documentation files change frequently as you fix bugs, enhance programs, and release new versions of the software. The task becomes even more complex when more than one version of each file is active. Frequently customers are using one version of a file while a newer version is being modified. You can easily lose track of the versions and accidentally undo changes or duplicate earlier work.
To help avoid these kinds of problems, Linux includes CVS (Concurrent Versions System; www.cvshome.org) for managing and tracking changes to files. Although CVS can be used on any file, it is most often used to manage source code and software documentation. CVS is based on RCS (GNU's Revision Control System) and is designed to control the concurrent access and modification of source files by multiple users.
A graphical front end to CVS named TkCVS (page 429) simplifies the use of CVS, especially if you do not use it frequently enough to memorize its many commands and options.
CVS controls who is allowed to update files. For each update, CVS records who made the changes and why the changes were made. Because CVS stores the most recent version of a file and the information needed to re-create all previous versions, it is possible to regenerate any version of a file.
A set of versions for several files may be grouped together to form a release. An entire release can be re-created from the change information stored with each file. Saving the changes for a file rather than saving a complete copy of the file generally conserves a lot of disk space, well in excess of the space required to store each update in the CVS files themselves.
This section provides an overview of CVS and TkCVS. See the CVS-RCS-HOW-TO Document for Linux for more information.
CVS: Concurrent Versions System
CVS treats collections of files as single units, making it easy to work on large projects and permitting multiple users to work on the same file. CVS also provides valuable self-documenting features for its utilities.
Built-In CVS Help
CVS uses a single utility, cvs, for all its functions. To display the instructions for getting help, use the help option:
$ cvs --help Usage: cvs [cvs-options] command [command-options-and-arguments] where cvs-options are -q, -n, etc. (specify --help-options for a list of options) where command is add, admin, etc. (specify --help-commands for a list of commands or --help-synonyms for a list of command synonyms) where command-options-and-arguments depend on the specific command (specify -H followed by a command name for command-specific help) Specify --help to receive this message The Concurrent Versions System (CVS) is a tool for version control. For CVS updates and additional information, see the CVS home page at http://www.cvshome.org/ or Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html
To get help with a cvs command, use the help option followed by the name of the utility. The following example shows help for the log command:
$ cvs --help log Usage: cvs log [-lRhtNb] [-r[revisions]] [-d dates] [-s states] [-w[logins]] [files...] -l Local directory only, no recursion. -R Only print name of RCS file. -h Only print header. -t Only print header and descriptive text. -N Do not list tags. -b Only list revisions on the default branch. -r[revisions] Specify revision(s)s to list. rev1:rev2 Between rev1 and rev2, including rev1 and rev2. rev1::rev2 Between rev1 and rev2, excluding rev1 and rev2. rev: rev and following revisions on the same branch. rev:: After rev on the same branch. :rev rev and previous revisions on the same branch. ::rev Before rev on the same branch. rev Just rev. branch All revisions on the branch. branch. The last revision on the branch. -d dates Specify dates (D1<D2 for range, D for latest before). -s states Only list revisions with specified states. -w[logins] Only list revisions checked in by specified logins. (Specify the --help global option for a list of other help options)
Options for individual cvs commands (command options) go to the right of the individual command names. Options to the cvs utility itself, such as the help option to the log command, go to the left of all individual command names (that is, they follow the word cvs on the command line). The two types of options sometimes use the same letter yet may have an entirely different meaning.
How CVS Stores Revision Files
With CVS, revision files are kept in a common area called a source repository. This area is identified by the value of the environment variable CVSROOT, which holds the absolute pathname of the repository. The system administrator can tell you what value of CVSROOT to use, or you can create your own private repository and have CVSROOT point to it.
The source repository is organized as a hierarchical collection of files and directories. CVS does not limit you to checking out one file at a time; you can check out an entire subdirectory containing many files typically all the files for a particular project. A subdirectory of CVSROOT that can be checked out as a single unit is called a module. Several people can check out and simultaneously modify the files within a single module.
CVS users typically store all the modules they are currently working on in a special directory. If you want to follow this practice, you must use cd to make that special directory the working directory before you check out a module. When you check out a module, CVS replicates the module's tree structure in the working directory. Multiple developers can check out and edit CVS files simultaneously because the originals are retained in the source repository; the files in the repository undergo relatively infrequent modification in a controlled manner.
Basic Cvs Commands
Although many cvs commands are available, a handful of commands allows a software developer to use CVS and to contribute changes to a module. A discussion of some useful commands follows. All examples assume that the appropriate modules have been installed in the CVS source repository. "Adding a Module to the Repository" (page 426) explains how to install a module.
Of the commands discussed in this section, cvs commit is the only one that changes the source repository. The other commands affect only the files in the working directory.
To simplify examples in the following sections, the pathname of the working directory is given by the variable CVSWORK; all modules can be assumed to be subdirectories of CVSWORK. Although this variable has no special meaning to CVS, you may find it helpful to define such a variable for your own work.
Checking Out Files from the Source Repository
To check out a module from the CVS source repository, use the cvs checkout command. The following example checks out the Project2 module, which consists of four source files. First use cd to change working directories to the directory you want the module copied into (CVSWORK in this case). The cvs utility always copies into the working directory.
$ cd $CVSWORK $ ls Project1 $ cvs checkout Project2 cvs checkout: Updating Project2 U Project2/adata.h U Project2/compute.c U Project2/randomfile.h U Project2/shuffle.c $ ls Project1 Project2 $ ls Project2 CVS adata.h compute.c randomfile.h shuffle.c
The name of the module, Project2, is given as an argument to cvs checkout. Because the Project2 directory does not already exist, cvs creates it in the working directory and places copies of all source files for the Project2 module into it: The name of the module and the name of the directory holding the module are the same. The checkout command preserves the tree structure of the cvs module, creating subdirectories as needed.
The second ls command after checkout reveals, in addition to the four source files for Project2, a directory named CVS. The CVS system uses this directory for administrative purposes; you do not normally access it.
Once you have your own copies of the source files, you can edit them as you see fit. You can change files within the module even if other developers are modifying the same files at the same time.
Making Your Changes Available to Others
To check in your changes so that others have access to them, you need to run the cvs commit command. When you give this command, cvs prompts you to provide a brief log message describing the changes, unless you use the m option. With this option, cvs uses the string following the option as the log message. The file or files that you want to commit follow the optional log message on the command line:
$ cvs commit -m "function shuffle inserted" compute.c cvs commit: Up-to-date check failed for 'compute.c' cvs [commit aborted]: correct above errors first!
Here the cvs utility reports an error because the version of compute.c that you modified is not up-to-date. A newer version of compute.c has been committed by someone else since you last checked it out of the source repository. After informing you of the problem, cvs exits without storing your changes in the source repository.
To make your version of compute.c current, you need to run the update command. A subsequent commit will then succeed, and your changes will apply to the latest revision in the source repository.
Updating Your Copies with Changes by Others
As the preceding example shows, CVS does not notify you when another developer checks in a new revision of a file after you have checked out your working copy. You learn this fact only when you attempt to commit your changes to the source repository. To incorporate up-to-date revisions of a CVS source file, use the cvs update command:
$ cvs update compute.c RCS file: /usr/local/src/master/Project2/compute.c,v retrieving revision 1.9 retrieving revision 1.10 Merging differences between 1.9 and 1.10 into compute.c M compute.c
The changes made to the working copy of compute.c remain intact because the update command merges the latest revision in the source repository with the version specified on the update command line. The result of the merge is not always perfect, however. The cvs update command informs you if it detects overlapping changes.
Adding New Files to the Repository
You can use the cvs add command to schedule new files to be added to the source repository as part of the module you are working on. Once you have moved to the directory containing the files, give the cvs add command, listing the files you want to add as arguments:
$ cd $CVSWORK/Project2 $ ls CVS compute.c shuffle.c tabout2.c adata.h randomfile.h tabout1.c $ cvs add tabout[1-2].c cvs add: scheduling file 'tabout1.c' for addition cvs add: scheduling file 'tabout2.c' for addition cvs add: use 'cvs commit' to add these files permanently
The add command marks the files tabout1.c and tabout2.c for entry into the repository. These files will not be available for others until you give a commit command. This staging allows you to prepare several files before others incorporate the changes into their working copies with the cvs update command.
Removing Files from the Repository
The cvs remove command records the fact that you wish to remove a file from the source repository. Like the add command, it does not affect the source repository. To delete a file from the repository, you must first delete your working copy of the file, as the following example shows:
$ cvs remove shuffle.c cvs remove: file 'shuffle.c' still in working directory cvs remove: 1 file exists; use 'rm' to remove it first $ rm shuffle.c $ cvs remove shuffle.c cvs remove: scheduling 'shuffle.c' for removal cvs remove: use 'cvs commit' to remove this file permanently
After using rm to delete the working copy of shuffle.c, invoke a cvs remove command. Again, you must give the commit command before the file is actually removed from the source repository.
Other CVS Commands
Although the commands given earlier are sufficient for most work on a module, you may find some other commands to be useful as well.
Tagging a Release
You can apply a common label, or tag, to the files in a module as they currently exist. Once you have tagged files of a module, you can re-create them in exactly the same form even if they have been modified, added, or deleted since that time. This ability enables you to freeze a release yet allows development to continue on the next release:
$ cvs rtag Release_1 Project1 cvs rtag: Tagging Project1
Here the Project1 module has been tagged with the label Release_1. You can use this tag with the cvs export command to extract the files as they were frozen at this time.
Extracting a Release
The cvs export command lets you extract files as they were frozen and tagged:
$ cvs export -r Release_1 -d R1 Project1 cvs export: Updating R1 U R1/scm.txt
This command works like the cvs checkout command but does not create the CVS support files. You must give either the r option to identify the release (as shown above) or a date with the D option. The d R1 option instructs cvs to place the files for the module into the directory R1 instead of using the module name as the directory.
Removing Working Files
When you are finished making changes to the files you have checked out of the repository, you may decide to remove your copy of the module from your working directory. One simple method is to move into the working directory and recursively remove the module. For example, if you want to remove your working copy of Project2, you could use the following commands:
$ cd $CVSWORK $ rm -rf Project2
The repository will not be affected by removing these files. However, if you had made changes to the files but had not yet committed those changes, they would be lost if you used this approach. The cvs release command is helpful in this situation:
$ cd $CVSWORK $ cvs release -d Project2
The release command also removes the working files but first checks each one to see whether it has been marked for addition into the repository but has not yet been committed. If that is the case, the release command warns you and asks you to verify your intention to delete the file. You can fix the problem at this point if you like and redo the release command. The release command also warns you if the repository holds a newer version of the file than the one in your working directory. Thus you have the opportunity to update and commit your file before deleting it. (Without the d option, your working files will not be deleted, but the same sequence of warning messages will be given.)
Adding a Module to the Repository
The discussion of CVS to this point assumes that a module is already present in the CVS source repository. If you want to install a directory hierarchy as a new module in the repository or update an existing module with a new release that was developed elsewhere, go to the directory that holds the files for the project and run the cvs import command. The following example installs the files for Project1 in the source repository:
$ cvs import -m "My first project" Project1 ventag reltag
The m option allows you to enter a brief description of the module on the command line. Following the description is the directory or the pathname of the directory under CVSROOT that you want to hold the module. The last two fields are symbolic names for the vendor branch and the release. Although they are not significant here, they can be useful when releases of software are supplied by outside sources.
You can now use the cvs checkout command to check out the Project1 module:
$ cvs checkout Project1
Before you install a CVS repository, think about how you would like to administer it. Many installations have a single repository where separate projects are kept as separate modules. You may choose to have more than one repository. The CVS system supports a single repository that is shared across several computer systems using NFS.
Inside a repository is a module, named CVSROOT that contains administrative files (here CVSROOT is the name of a module and is different from the CVSROOT directory). Although the files in this module are not required to use CVS, they can simplify access to the repository.
Do not change any files in the CVSROOT module by editing them directly. Instead, check out the file you want to change, edit the checked-out copy, and then check it back in, just as you would with files in any other module in the repository. For example, to check out the modules file from the CVSROOT module, use the command
$ cvs checkout CVSROOT/modules
This command creates the directory CVSROOT in your working directory and places a checked-out copy of modules in that directory. After checking it out, you can edit the modules file in the CVSROOT directory:
$ cd CVSROOT $ vim modules
After you edit the modules file, check it back into the repository:
$ cd .. $ cvs checkin CVSROOT/modules
Of all the administrative files in the CVSROOT module, the modules file is the most important. You can use this file to attach symbolic names to modules in the repository, allow access to subdirectories of a module as if they were themselves modules, and specify actions to take when checking specific files in or out.
Most repositories start with a modules file that allows you to check out the modules file with the following command, instead of the one shown earlier:
$ cvs checkout modules
With the preceding command CVS creates a subdirectory named modules within the working directory, instead of one named CVSROOT. The modules file is then checked out into this directory.
The following is an example of a modules file (the lines that start with # are comment lines and, along with blank lines, are ignored by CVS):
# The CVS modules file # # Three different line formats are valid: # key -a aliases... # key [options] directory # key [options] directory files... # # Where "options" are composed of: # -i prog Run "prog" on "cvs commit" from top-level of module. # -o prog Run "prog" on "cvs checkout" of module. # -t prog Run "prog" on "cvs rtag" of module. # -u prog Run "prog" on "cvs update" of module. # -d dir Place module in directory "dir" instead of module name. # -l Top-level directory only -- do not recurse. # # And "directory" is a path to a directory relative to $CVSROOT. # # The "-a" option specifies an alias. An alias is interpreted as if # everything on the right of the "-a" had been typed on the command line. # # # You can encode a module within a module by using the special '&' # character to interpose another module into the current module. This # can be useful for creating a module that consists of many directories # spread out over the entire source repository. # Convenient aliases world -a . # CVSROOT support; run mkmodules whenever anything changes. CVSROOT -i mkmodules CVSROOT modules -i mkmodules CVSROOT modules loginfo -i mkmodules CVSROOT loginfo commitinfo -i mkmodules CVSROOT commitinfo rcsinfo -i mkmodules CVSROOT rcsinfo editinfo -i mkmodules CVSROOT editinfo # Add other modules here... testgen testgen testdata1 testdata1 testdata2 testdata2 testdata3 testdata3 testdata4 testdata4 testcode testgen/_code cvs cvs
The lines after the comment and blank lines define symbolic names for many modules. For example, the following line defines world to be an alias for the root of the CVS repository:
world -a .
You can use such names in CVS commands as the names of modules. For example, the following command checks out the entire repository (probably not a good idea):
$ cvs checkout world
In the sample modules file, the administrative files have been given definitions that attach both a symbolic name to the file and an action ( i mkmodules) to take when each file is checked into the repository. The i mkmodules action causes CVS to run the mkmodules program when the file is checked in. This program ensures that a copy of the checked-in file exists in a location where CVS can locate it.
Following the action is the name of the subdirectory in CVSROOT where any files associated with the symbolic name are located. Any remaining arguments on the line are the names of specific files within that directory.
The following line identifies CVSROOT as the name for the module in the directory $CVSROOT/CVSROOT that is, for all the administrative files for CVS:
CVSROOT -i mkmodules CVSROOT
Similarly the following line associates the modules module with the modules file within the CVSROOT directory:
modules -i mkmodules CVSROOT modules
The preceding line allows the following command to find and check out the modules file:
$ cvs checkout modules
The last set of lines in the sample modules file associates symbolic module names with directories and files in the repository.
The cvs utility is useful enough that an X Window System interface, TkCVS (www.twobarleycorns.net/tkcvs.html), has been written for it using the Tk extension to the Tcl programming language (tcl.sourceforge.net). It provides a convenient point-and-click interface to CVS (Figure 10-5). After you have downloaded and installed TkCVS, start it by using cd to change to the directory you want to work in and entering the following command:
$ tkcvs &
Figure 10-5. The TkCVS utility
All operations are available through the pull-down menus at the top of the window. Along the bottom are buttons for accessing the most common actions. A description of the action bound to a button appears when you position the mouse pointer on top of a button.
In the middle of the window is a browse list. Move into a subdirectory by double-clicking the left mouse button while the mouse pointer is on the directory name in the list. Edit a file by double-clicking the filename. To select more than one file, hold down the left mouse button and drag the mouse pointer across several names. Clicking the right mouse button will mark all selected files. Some of the operations (such as viewing the revision log messages) will work on all marked files.
The Help pull-down menu in the upper-right corner is an excellent way to learn how TkCVS works. For example, when you select the Help menu item CVS modules file..., an explanation of the lines that you can add to the CVS modules file to support TkCVS better appears in a window. If you choose not to add these lines to the modules file, some TkCVS commands, such as browsing the repository, may not display all available modules.
|< Day Day Up >|