Source Code Management

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 crops up regularly 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. In many situations 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, Mac OS X includes CVS (Concurrent Versions System; see and for managing and tracking changes to files. Although CVS can be used on any file, it is most often employed 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.

An OS Xspecific graphical front end to CVS named CVL (Concurrent Versions Librarian) simplifies the use of CVS, especially if you do not use it frequently enough to memorize its many commands and options. CVL is not provided with OS X; you can download it from TkCVS (page 518) is another GUI front end to CVS. It is available for Mac OS X; you can download it from

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 spacewell 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 man page and the CVS home page 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.

Builtin 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 or     Pascal Molli's CVS site at

To get help with a cvs command, use the help option followed by the name of the command. The following example shows help information 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.         -S      Do not print name/header if no revisions selected.         -b      Only list revisions on the default branch.         -r[revisions]   A comma-separated list of revisions to print:            rev1:rev2   Between rev1 and rev2, including rev1 and rev2.            rev1::rev2  Between rev1 and rev2, excluding rev1.            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       rev and previous revisions on the same branch.            rev         Just rev.            branch      All revisions on the branch.            branch.     The last revision on the branch.         -d dates        A semicolon-separated list of 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 to use for CVSROOT, 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 filestypically 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 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 therefore 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, knowledge of just 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 515) 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 make the directory you want the module copied into (CVSWORK in this case) the working directory. 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 other users 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. That is, 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. For this reason, 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 used cd to make the directory containing the files the working directory, 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 to 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; 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.

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 existed when they were frozen.

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 approach 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, the changes 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 you will receive the same sequence of warning messages.)

Adding a Module to the Repository

The discussion of CVS to this point assumed that a module was 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

CVS Administration

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 following 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 example shows a modules file (the lines that start with # are comment lines and, along with blank lines, are ignored by CVS):

# 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. #       -e prog       Run "prog" on "cvs export" 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. # # NOTE: If you change any of the "Run" options above, you'll have to # release and re-checkout any working directories of these modules. # # 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 . modules    -d . CVSROOT modules # 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 a symbolic name to the file.

Following the action is the name of the subdirectory in CVSROOT that holds any files associated with the symbolic name. Any remaining arguments on the line are the names of specific files within that directory.

The following line associates the modules module with the modules file within the CVSROOT directory:

modules     -d . CVSROOT modules

The d . option forces CVS to check out the file into the user's working directory instead of creating a new directory named 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.

Using TkCVS

The cvs utility is useful enough that a graphical interface, TkCVS, has been written for it using the Tk extension to the Tcl programming language ( It provides a convenient point-and-click interface to CVS (Figure 12-5). After you have downloaded and installed TkCVS (, you can start the utility by opening the directory you installed it in and double-clicking the TkCVS icon.

Figure 12-5. The TkCVS utility

All operations are available through the pull-down menus found at the top of the window. Along the bottom of the window are buttons for accessing the most common actions. A description of the action bound to a button appears when you position the mouse pointer over 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 this 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 operations (such as viewing the revision log messages) will work on all marked files.

The Help pull-down menu in the upper-right corner of the window 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 better support TkCVS 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.

A Practical Guide to UNIX[r] for Mac OS[r] X Users
A Practical Guide to UNIX for Mac OS X Users
ISBN: 0131863339
EAN: 2147483647
Year: 2005
Pages: 234

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: