Essential CVS/Using CVS/Basic Use of CVS
This chapter provides a thorough discussion of the most critical CVS commands and topics. It is designed for end users who will not have to administrate the repository and who will not have to make changes that affect the entire project.
The commands explained in this chapter include checkout, commit, update, release, add, remove, and status. Other topics in this chapter include an explanation of sandboxes, merging, conflicts, binary and special files, keywords, editing files in CVS, and the CVS command syntax.
This chapter assumes that you have installed CVS, set up a repository, and created a project. Instructions for these tasks are in Chapter 2. Chapter 2 also touches on many of the commands in this chapter, but this chapter provides a full explanation of their uses.
CVS stores project data in a repository, but you don't work directly from the repository. You work from a sandbox. A sandbox may be on the same machine as the repository, on a machine on the same local network, or on a machine connected through the Internet or another wide-area network. Figure 3-1 illustrates some of these possibilities.
The sandbox is a directory on a client machine, that contains a copy of a project's files. Sandboxes are usually within a user's home directory. All of a given project's files should be underneath the top directory, but the files may be in as many subdirectories as are desired. Every subdirectory contains a special CVS directory, with metadata files.
If you want to install your project over several directories or outside of your home directory, that should be part of your build or installation script. The sandbox is a place for making changes; it's not a place for running the project.
Sandboxes and repositories do not exist on a one-to-one basis; many sandboxes may share the same repository. To ensure that the repository does not become unstable, the repository locks files that are being changed. (The locks are actually over entire directories.) Occasionally, a developer will get a warning message that the repository is waiting on a lock, as shown in Example 3-1.
Example 3-1. Lock message
cvs server: [23:20:43] waiting for jenn's lock in /var/lib/cvs/wizzard/src
This message indicates that CVS is waiting on the other developer's lock in the specified directory. If a CVS process is killed before it's finished tidying up, a lock file may be created and not cleared. If CVS seems to be taking an inordinate amount of time to clear a lock, your repository administrator can clear it manually. Chapter 6 provides instructions and an example of how to do so.
CVS Command Syntax
CVS commands follow the syntax:
cvs [cvs-options] command [command-options] [arguments]
The cvs-optionsmodify the behavior of CVS as a whole, and their functions include help, quiet operation, changing the default editor, and changing the CVS root directory.
The command-options modify the command's behavior and can change which parts of the sandbox, or which revisions in the repository, a command will operate on.
Here are the cvs-options (left-side options) that you will use most often:
- -H or --help
- Displays information about the CVS command, but does not execute it.
- -Q or -q
- Suppresses informational messages. -q is quiet; -Q is very quiet and only prints warnings.
- -d repository_path
- Tells CVS which repository to use to run the command on.
- -e editor
- Changes the editor CVS calls when prompting for messages.
- Does not change any files. This is useful when trying to figure out what a command does, without risking damage to the repository or the sandbox.
- -z compression_level
- Compresses the file transfer over a network.
In this book, the command-options (right-side options) are discussed with their commands. Full lists of each set of options are available in Chapter 10.
At the command line, documentation for the CVS options is available with cvs --help-options. Command options for each command are available with cvs -H command. The list of all available CVS commands is available with cvs -help-commands.
Choosing Your Editor
In Unix and Linux, CVS calls the vieditor by default when asking for log messages. There are several ways you can change the default editor.
CVS checks the command line, the .cvsrc file, or your environment variables to see whether you have set an editor. You can use any of the following options to set an editor. These options are in order; the earliest option takes precedence.
- Call CVS with the -e editor option.
- Set the cvs -e editor line in your .cvsrc file on the client machine.
- Set the environment variables CVSEDITOR , EDITOR, or VISUAL on the client machine as the calling user. CVSEDITOR is preferred and overrides EDITOR and VISUAL.
You can avoid calling an editor at all by using the -m message command option. This option is available with add, commit, and import.
Sandboxes and Repositories
A sandbox is a local copy of a project's files, used to make changes and test work. Each developer should work from her own sandbox on a computer that is convenient to her.
The CVS repository contains the master copies of a project's files and their full histories. The repository may be on the same machine as the sandbox or on a remote machine accessed across a network. The repository is explained more fully in Chapter 6.
Every directory in the sandbox contains a CVS subdirectory. This directory has several files; the most important are Root, Repository, and Entries. The Root file contains the path to the sandbox's repository, the Repository file contains the subpath within the repository that leads to the directory in question, and the Entries file holds metadata about the files in the directory. The CVS subdirectory is explained more fully in Chapter 6.
Permissions and Ownership
Files lose their permissions when they are transferred to the repository. CVS normally will check out files with read and write permissions, but it can be configured to check them out as read-only. The person who checks a file out into the sandbox becomes the file's owner.
CVS works on many operating systems, each of which has its own way of recording ownership of files. The repository might not be on the same machine or have the same operating system as the sandbox. These circumstances may cause files to lose their ownerships and group memberships when the files are transferred to the repository, especially if the owning user does not exist on the repository machine. If the sandbox is connected to the repository through a proxy or network tunnel, the existence of appropriate users and groups on intermediate machines can also affect the ownership of files.
Group ownership of files in the repository is important, because CVS prevents users from checking out files they do not have read access to. Chapter 6 explains ownership and security issues with CVS.
If the ownership of, and permissions on, files is important to your project, you should set them in build and installation scripts. This issue usually affects projects that are installed for production use. Chapter 7 discusses this topic in more detail.
When you create a sandbox, you need to specify the repository to which it is connected. You do this by setting the repository path, either by putting it in the CVSROOT environment variable on your client computer, or by declaring it in the -d command option when you check out the sandbox. CVS stores the repository path in the sandbox.
The repository path is simply the path CVS uses to find the repository. The general format for repository paths is:
Each access method (method in the syntax) has a slightly different syntax. Chapter 8 provides the correct syntax for each method.
These are the access methods:
- Connect to the local machine.
- Connect using an externally defined rsh or rsh-like connection method (such as ssh)
- Connect using the internal rsh server (available only on some operating systems).
- Connect using the pserver (password server) connection method.
- Connect through the GSS-API (currently used for Kerberos 5.0).
- Connect through Kerberos 4 and earlier.
- Connect to a local machine as if it were a remote machine, using pipes for communication (useful if you are trying to diagnose problems).
Everything except the path itself may be left out of a repository path definition.
If the method is left out but the host is included, CVS uses either the server or the ext method, depending on whether an internal RSH server is available. If both the host and the method are left out, CVS will use the local access method.
If user is left out, CVS uses the current, operating-system login username. If password is left out but is required, CVS asks for it.
Chapter 8 explains repository connection methods.
Creating a Sandbox
The cvs checkout command is used to create a sandbox. Once the sandbox is created, checkout no longer needs to be used in that sandbox; update is the preferred command from that point. However, checkout may be called in a sandbox, in which case it is similar to update -d. 
checkout is called with the names of files, directories, or modules in the repository. A module is a collection of files and directories under one root directory that has been given a module name. Chapter 7 explains modules.
The syntax of cvs checkout is:
cvs [cvs-options] checkout [command-options] project
cvs checkout directoryand cvs checkout directory/ are identical. However, cvs checkout moduleand cvs checkout directory/ are different, unless the module happens to refer to a directory of the same name at the root level in the repository.
You must provide the path to the repository that contains the module or directory. This can be done with the CVSROOT environment variable on the client machine, or with the -d repository_path CVS option. If your repository is on a local machine, the repository path is the full path of your CVS repository's root directory. If your repository is on a remote machine, contact your system administrator and request the path for the repository. Once you have created a sandbox, you will not need to use the repository path for that sandbox again.
Section 3.2 earlier in this chapter discusses accessing repositories.
If you expect to use a repository for many sandboxes, specify its path using the CVSROOT environment variable. If you expect to use it only for one sandbox, use the-dCVS option.
checkout creates a new directory in the current working directory. By default, this directory has the name of the module, file, or directory being checked out.
checkout creates a CVS subdirectory in every directory of the sandbox. CVS keeps administrative files in this subdirectory, including the Root file that contains the address of the repository the sandbox came from. The Repository file contains the module name, if applicable, or the path from Root to reach the contents of the directory.
The following command options are commonly used with cvs checkout and can also be used with cvs update:
- Prunes empty directories.
- -D date or -r revision or -r tag
- Checks out a specific revision of the module based on date, revision, or tag.
- Forces CVS to check out the latest revision of a file if the date specified with -D doesn't match any date of the file or if the revision specified by -r doesn't match any revision of the file. -f is useful only with -D or -r. Use this option carefully, as it can cause confusion.
- -j revision or -j revision1 -j revision2
- Merges revisions. With one -j, CVS merges the changes between a common ancestor and the specified revision into the current sandbox. The common ancestor is the most recent revision that predates both the specified revision (found in the repository) and the sandbox revision.
With two revisions specified, CVS determines the differences between revision1 and revision2 and then merges those changes into the sandbox.
Example 3-2 shows the wizzard project being checked out of a CVS repository.
Example 3-2. Using cvs checkout
bash-2.05a$ ls cvsbook linuxchix newsforge oreilly bash-2.05a$ cvs -d cvs:/var/lib/cvs checkout wizzard cvs server: Updating wizzard U wizzard/Changelog U wizzard/INSTALL U wizzard/Makefile U wizzard/README U wizzard/TODO cvs server: Updating wizzard/doc cvs server: Updating wizzard/lib cvs server: Updating wizzard/man cvs server: Updating wizzard/src U wizzard/src/main.c U wizzard/src/wizzard.h bash-2.05a$ ls cvsbook linuxchix newsforge oreilly wizzard bash-2.05a$ ls wizzard Changelog CVS doc INSTALL lib Makefile man README src TODO
The need to retrieve a list of the projects stored in the CVS repository is common. The command cvs -d repository_path checkout -c provides a list of the modules registered in the modules file in the repository. Unfortunately, this command lists only modules and does not include files and directories that are not part of a module. Modules are explained in Chapter 7.
The command cvs -d repository_path checkout downloads everything in the repository, which usually is not what you desire. If you have direct access to the repository, listing the root directory of the repository provides a full list of project root directories. Combining this with the list of modules from checkout -c provides a complete list of projects.
There are two ways to switch the repository that a sandbox is checked out from:
- The official, recommended way is to commit all changes, use cvs release to release the sandbox, delete the sandbox, then check out a new sandbox from the new repository.
- The other way is to edit CVS/Root in all the directories in the sandbox. Unless you have only one directory, this actually is more work than the first way. It also means that some of the CVS history tracking may be lost.
Editing Sandbox Files
Once files are in your sandbox, you can edit them normally. For files saved as text, use your favorite text editor.
If you intend to produce text but prefer an editor that provides page and style formatting, be aware that files from editors that save in a nontext file format need to be stored in binary mode, which prevents some of CVS's most useful functions from working. File formats such as RTF, TeX, XML, HTML, and LaTeX are text-based and can be used with CVS without needing to be stored in binary mode.
If you are producing an image or some other nontext file, add the file to CVS as a binary file, as explained in Section 3.6 later in this chapter.
Committing Changes to the Repository
Files are edited in the sandbox, but changes to the sandbox have no effect on the repository until they are committed. The cvs commit command uploads changes from the sandbox to the repository. After determining which files need to be changed in the repository, cvs commit opens an editor and expects you to enter a log message.
Section 3.1.3 earlier in this chapter explains how to change the default editor.
The syntax of cvs commit is:
cvs [cvs-options] commit [command-options] [filename]
cvs commithas only a few options:
- Perform a local, nonrecursive commit operation on the current working directory only.
- Perform a recursive commit operation on all subdirectories, as well as the current directory (default).
- -m message
- Provide a log message.
- -F filename
- Provide a log message from the specified file.
- -r revision
- Set an updated revision number (not recommended for novice users).
Example 3-3 shows a typical cvs commit. The vertical ellipsis denotes the point at which CVS normally calls the editor. Example 3-4 shows the default text displayed in the editor and the log message for this commit.
Example 3-3. Using cvs commit
/home/jenn/cvs/wizzard$ cvs commit cvs commit: Examining . cvs commit: Examining doc cvs commit: Examining lib cvs commit: Examining man cvs commit: Examining src . . . RCS file: /var/lib/cvs/wizzard/src/main.c,v done Checking in src/main.c; /var/lib/cvs/wizzard/src/main.c,v <-- main.c initial revision: 1.1 done RCS file: /var/lib/cvs/wizzard/src/wizzard.h,v done Checking in src/wizzard.h; /var/lib/cvs/wizzard/src/wizzard.h,v <-- wizzard.h initial revision: 1.1 done /home/jenn/cvs/wizzard$
Example 3-4. Entering log messages for cvs commit
Added main.c: parses parameters and calls functions in other files. Added wizzard.h: defines compile-time global variables. CVS: ------------------------------------------------------------------ CVS: Enter Log. Lines beginning with `CVS:' are removed automatically CVS: CVS: Committing in . CVS: CVS: Added Files: CVS: src/main.c src/wizzard.h CVS: ------------------------------------------------------------------
By default, cvs commit operates recursively on the current working directory. It can also take files or directories as parameters and operate recursively them.
Use either of the following variations of cvs commit to avoid having to enter a message during the commit process:
cvs commit -m message
cvs commit -F filename
Examples 3-3 and 3-4 show a recursive commit, which commits files not only in your current working directory, but also in all subdirectories. If you want to commit only the current working directory (sometimes called the local directory), use cvs commit -l.
Use cvs status or cvs update -n to find out which files need to be updated or committed.
Setting Revision Numbers
You can use the -r option of cvs commit to set every file in a project to a specific revision number. This option is not used often; if it is used, it's usually by the project lead. The option changes the head revision number of all files, regardless of whether they've changed in the sandbox. The revision number must be higher than any number currently in the repository, and it must be in the same format as the existing revision numbers for the files.
CVS developers recommend you use tags to track revisions, and leave the internal revision numbers as CVS sets them by default. Chapter 4 explains how to use tags.
When to Commit
If your changes will not affect anyone else, commit frequently. Commit every time you'd hate to have to redo your work. Frequent commits keep your work in a single place for backup. If you are working in a team, frequent commits and updates reduce the chance of having to do a major, difficult merge.
If your changes will affect others, especially in a way that risks breaking the build, commit every time the effect will be negligible. For example, run a test-compile before lunch and before you leave, and commit if it compiles.
Don't ever work for long without committing. If a full day's work doesn't compile, wrap comment tags around your changes and commit the commented-out code or consider committing to a branch. Always speak to your project manager before branching.
Your project manager may have a commit strategy; if so, follow that. Chapter 7 discusses commit strategies in more detail.
Checking File Status
The cvs status command is a quick way to determine which files are up-to-date and which need to be committed or merged.
Files that have not been added to the repository are prefixed with a question mark (?). Files stored in CVS are shown with the filename, the current status, the working (or sandbox) revision, the revision currently stored in the repository and its location in the repository, and the sticky state of the file. Stickiness is explained in Chapter 4.
The syntax of cvs status is:
cvs [cvs-options] status [command-options] [filename]
The status command has only three options:
- Perform local, nonrecursive operation on this directory only.
- Perform recursive operation on all subdirectories, as well as the current directory (default).
- Use verbose mode (display information about tags as well).
Example 3-5 shows the CVS status report for the wizzard.hfile.
Example 3-5. Output from the cvs status command
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = File: wizzard.h Status: Up-to-date Working revision: 1.5 Repository revision: 1.5 /var/lib/cvs/wizzard/src/wizzard.h,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none)
A file may be in one of the following states:
- The file in the sandbox is synchronized with the file in the repository.
- Needs Checkout
- The file does not exist in the sandbox; it exists only in the repository.
- Needs Patch
- The file in the sandbox has not been modified, and the file in the repository is more recent. The sandbox file needs to be patched using cvs update in order to be brought up-to-date with the repository.
- Unresolved Conflict
- The repository copy and the sandbox copy cannot be merged. This status occurs when you have a file in the sandbox with the same name as a file in the repository, but which you did not receive from the repository.
- Locally Added
- The file in the sandbox has been added, but the addition has not been committed.
- Locally Removed
- The file in the sandbox has been removed, but the removal has not been committed.
- File had conflicts on merge
- There is a known conflict between the file in the repository and the file in the sandbox.
- Locally Modified
- The file in the sandbox has been modified but not committed.
- Needs Merge
- The file in the repository does not match the file in the sandbox and both files have new data. The files need to be merged using cvs merge.
There are three error states:
- Classify Error
- CVS could not determine the state of this file.
- This file is not known to CVS. Normally, the cvs status command displays unknown files at the start of its sequence with a ?beside them. If an unknown file does get passed to the status command, CVS displays its name in the main body of its display with the status Unknown.
For example, if you run the command cvs status filename and the filename refers to a file that is not stored in the repository, CVS reports its status as Unknown.
- Entry Invalid
- The state of the repository and sandbox files does not match CVS's record keeping. This usually occurs when one of the files has been removed by editing the repository directly, or when a newly added file has been removed from the sandbox without calling cvs remove.
Note that the revision number shown in the status (and other places) is the CVS internal revision number; it has nothing to do with the version number that a file or project may have outside of CVS.
Updating the Sandbox Files from the Repository
The cvs commit command uploads changes from the sandbox to the repository; cvs update downloads changes from the repository to the sandbox. The two commands complement each other, and you need to call both to keep the sandbox synchronized with the repository. Use cvs commitwhen you have changed sandbox files since your last commit; use cvs update when you know that (or wish to check whether) the repository has been changed since you last updated.
cvs update attempts to preserve any changes you have made to your sandbox since you last synchronized it with the repository. These changes will be merged into the files retrieved from the repository. If you intend to overwrite your sandbox files with a clean repository copy, use the -C (clean) option in conjunction with any other options. Most often, you will use -C when you want to discard changes, but you can also use the -r (retrieve by revision), -D (retrieve by date), or -A(clear sticky tags) options.
Example 3-6 shows output from cvs update executed with the -d option. The -d option instructs CVS to download new directories from the repository to the sandbox.
Example 3-6. Using cvs update
bash-2.05a$ cvs update -d cvs server: Updating . cvs server: Updating doc cvs server: Updating doc/design U doc/design/Analysis.rtf U doc/design/Specification.rtf cvs server: Updating doc/plan U doc/plan/Schedule.rtf cvs server: Updating lib cvs server: Updating man cvs server: Updating src M src/wizzard.h
cvs update displays symbols next to each file it downloads. The symbols report file status, similar to those reported by cvs status. You'll see the following symbols in cvs update command output:
- A filename
- The file has been added to the sandbox, but it has not been committed.
- C filename
- There is a conflict between the repository copy and the sandbox copy; this conflict requires human intervention to resolve.
- M filename
- The file has been modified in the sandbox. Either the sandbox version had changes that the repository did not, or both the sandbox and the repository had changes that CVS could safely merge together.
- P filename
- The file has been patched in the sandbox. The repository copy changed, but not the sandbox copy, so the repository changes were added to the sandbox.
U and Preport the same effect in the sandbox: the file has been updated from the repository. P means that CVS downloaded a patch, and U means that it downloaded the whole file.
- R filename
- The file has been removed from the sandbox, but it has not been committed.
- U filename
- The file was updated successfully. Either a new revision from the repository has replaced the sandbox copy, or there was no sandbox copy and the repository revision has been checked out.
- ? filename
- The file is in the sandbox but not the repository, and it is not marked for addition to the repository.
If you don't want CVS to report on certain files, you can use the cvsignore features described in Chapter 6.
cvs update uses the following syntax:
cvs [cvs-options] update [command-options] [filename]
If used without a filename, cvs update updates the current working directory recursively. The most commonly used update options are:
- Pull down new directories.
- Avoid pulling down empty directories (not compatible with -d).
- -j revision or -j revision1 -j revision2
- Merge revisions. The revision parameter can be a revision number or a tag.
With one -j, CVS merges the changes between a common ancestor and the specified revision into the current sandbox. The common ancestor is the most recent revision that predates both the specified revision (found in the repository) and the sandbox revision.
With two revisions specified, CVS determines the differences between revision1 and revision2 and then merges the changes into the sandbox.
- Reset any sticky tags, dates, or keyword options and replace the existing files in the sandbox with the revision at the head of the trunk. CVS merges any changes you have made to the sandbox with the revision it downloads. Use -C as well as -Aif you want the changes overwritten.
- Overwrite files in the sandbox with copies from the repository.
- Perform a local, nonrecursive update operation on this directory only.
- Perform a recursive operation on all subdirectories, as well as the current directory (default).
- -D date or -r revision or -r tag
- Check out a specific revision of the module based on the given date, revision number, or tag. These options retrieve a static revision; they are not intended for undoing changes.
If a date is used, CVS selects the latest revision prior to that date. A date can include the time as well.
CVS attempts to preserve your changes since your last checkout, update, or commit and merge them with the revision it is retrieving.
- Force CVS to update to the latest revision of a file if the date specified with -D doesn't match any date of the file, or if the revision specified by -r doesn't match any revision of the file. This option is useful only with -D or -r. Use it carefully, as it can cause confusion.
- -W " wrapper string"
- Use file extensions to determine how to merge the file or files being updated.
Tags and stickiness are explained in Chapter 4. Wrappers and keywords are explained later in this chapter.
Retrieving Past Revisions of a File
You can use CVS to retrieve a past revision of a file. Use the cvs log command to find the revision number or tag for the revision you want to retrieve. Tag names or log messages can help you determine which revision has the data you want. Example 3-7 shows a typical cvs log message header and one revision message. The tags are listed under the "symbolic names" heading.
Example 3-7. cvs log output
RCS file: /var/lib/cvs/wizzard/src/wizzard.h,v Working file: src/wizzard.h head: 1.15 branch: locks: strict access list: symbolic names: bugfix_version_branch: 22.214.171.124 bugfix_branch_root: 1.14 keyword substitution: kv total revisions: 1; selected revisions: 1 description: . . . ---------------------------- revision 1.15 date: 2002/09/11 13:33:13; author: jenn; state: Exp; Started the multiple satellite tracking feature. = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
This chapter discusses only retrieving past revisions in the context of a single line of development. Chapter 4 describes forking development to produce two or more simultaneous development tracks.
Retrieving a static file
Calling cvs update with the -r or -D options downloads a static, unchangeable copy of the file or files to the sandbox. Such files can be useful to view past data, but changes to these files cannot be committed to the repository.
The static files have a mark, called a sticky tag or a sticky date, in the Entries file in the CVS subdirectory of the current sandbox directory. The command cvs update -A removes the sticky tags or dates and replaces the files with the latest revision from the repository. CVS attempts to merge any changes you have made to the sandbox copy into the copy it retrieves from the repository.
If you make changes to a static revision and want to commit the changed file to the repository as a new revision, create a backup of the changed file, use cvs update -A to clear the sticky state, replace the file that update created with the backup, and then cvs commit the file.
Example 3-8 shows the retrieval of an early version of the wizzard.h file.
Example 3-8. Retrieval by revision number
bash-2.05a$ cvs update -r 1.2 src/wizzard.h U src/wizzard.h bash-2.05a$ less src/wizzard.h /* * Wizzard.h * Sep 12 2002 * Developer: Jenn Vesperman * * Headers, macros and constants file for the Wizzard project. */
To revert a sandbox file to a previous revision, use the following form of the cvs update command:
cvs update -j sandbox_revision -j previous_revision
This command calculates the differences from the older revision to the newer revision, then applies the differences to the sandbox. Be careful to get the order right.
Example 3-9 shows reverting a messed-up version (1.3) of wizzard.h to the previous revision, using the -j option. The less commands are there only to show you the content of the files; they are not part of the process. You can use cvs log or cvs status to determine which revision is the current version of a file.
Example 3-9. Reverting changes with update -j
bash-2.05a$ less wizzard.h /* * Wizzard.h * Sep 14 2002 * Destroyer: Doppel * * Headaches, messes and constraints file for the Wizbang project. */ bash-2.05a$ cvs update -j 1.3 -j 1.2 wizzard.h RCS file: /var/lib/cvs/wizzard/src/wizzard.h,v retrieving revision 1.3 retrieving revision 1.2 Merging differences between 1.3 and 1.2 into wizzard.h bash-2.05a$ less wizzard.h /* * Wizzard.h * Sep 12 2002 * Developer: Jenn Vesperman * * Headers, macros and constants file for the Wizzard project. * */
You can also revert to a previous revision of a file with the following command:
cvs update -r revision -p > filename
This command uses the -p option of cvs updateto writethe specified revision to stdout. That output is then redirected to filename using the > shell operator. The> operator is a shell redirection operator and may vary depending on the shell you use. The> filename part of the command is processed by the shell; it is not passed to CVS.
Example 3-10 reverts the corrected revision of wizzard.h to the corrupted revision, using the -poption. The less command shows the contents of the file after the reversion.
Example 3-10. Reverting changes with update -r -p
bash-2.05a$ cvs update -r 1.3 -p > wizzard.h cvs server: Updating . = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Checking out wizzard.h RCS: /var/lib/cvs/wizzard/src/wizzard.h,v VERS: 1.3 *************** bash-2.05a$ less wizzard.h /* * Wizzard.h * Sep 14 2002 * Destroyer: Doppel * * Headaches, messes and constraints file for the Wizbang project. */
Using cvs commitafter retrieving with either method adds the current contents of the sandbox file (identical to the old revision) to the repository as the newest revision.
Retrieving by date
The -Doption retrieves the most recent revision that precedes the date and time you specify. CVS accepts a wide range of date formats, including ISO 8601, RFC 822, and RFC 1123, as well as certain English terms such as "yesterday." Chapter 11 provides the full range of date formats.
The date formats YYYY-MM-DD and YYYY-MM-DD HH:MM are acceptable and fairly universal. You can also use the date and time formats from cvs log output.
CVS repositories use Coordinated Universal Time (UTC) rather than your local time, so it can be useful to include the time zone at the end of a date string. If you don't specify a time zone, CVS assumes that you intend your time or date string to be in local time.
Times in cvs log output are in UTC. If you copy a time from cvs log to use for a -D option, either specify the UTC time zone or modify the time to local time.
If the time is not specified along with a date, CVS locates the latest revision that is older than that date—the revision that was active at midnight at the start of the date. Example 3-11 demonstrates retrieving the revision of wizzard.h that was current at 2 P.M. on 13 September 2002.
Example 3-11. Retrieving with update -D
bash-2.05a$ cvs update -D 2002-09-13 14:00 src/wizzard.h U src/wizzard.h bash-2.05a$ less wizzard.h /* * Wizzard.h * Sep 12 2002 * Developer: Jenn Vesperman * * Headers, macros and constants file for the Wizzard project. */
When to Update
Update frequently. Always update before beginning work—perhaps first thing in the morning and just after lunch. This ensures that any changes are merged often. Frequent commits and updates leave little chance of having to do a major, pain-in-the-neck merge.
In programming projects, if people are careful about ensuring that their code compiles before a commit, their commits won't break your code gratuitously. If your code doesn't work after an update, you can check to see who made the change that broke it and speak to them immediately. Frequent commits and updates catch these problems early.
Conflicts and Merging
CVS attempts to merge files using a line-based merging system. If the changes are on different lines, this system just adds, replaces, or removes lines as appropriate. CVS uses an internal implementation of the diff and patch programs to merge files.
Example 3-12. File merge and conflict during update
bash-2.05a$ cvs update cvs server: Updating . RCS file: /var/lib/cvs/wizzard/src/main.c,v retrieving revision 1.1 retrieving revision 1.2 Merging differences between 1.1 and 1.2 into main.c rcsmerge: warning: conflicts during merge cvs server: conflicts found in main.c C main.c RCS file: /var/lib/cvs/wizzard/src/wizzard.h,v retrieving revision 1.3 retrieving revision 1.4 Merging differences between 1.3 and 1.4 into wizzard.h M wizzard.h bash-2.05a$
If a line in the repository copy is different than the corresponding line in the sandbox copy, CVS reports a conflict and creates a file with the two revisions of the line surrounded by special marks, as shown here:
<<<<<<< filename sandbox content = = = = = = = repository content >>>>>>> revision
The original file is stored in .#file.revision in the file's working directory, and the results of the merge are stored as the original filename.
CVS creates a set of conflict marks and content revisions for every conflict in the file. If several neighboring lines have a conflict, CVS produces a single set of conflict marks around the group of lines, as shown in Example 3-13.
Example 3-13. Conflicts in a file
<<<<<<< main.c /* * main.c * Sep 12 2002 * Developer: Doppel * * Main program file for the Wizbang project. */ = = = = = = = /* * main.c * Sep 12 2002 * Developer: Jenn Vesperman * * Main program file for the wizzard project. */ >>>>>>> 1.2
To resolve a conflict, search for the conflict marks and edit the file; then commit the changed file to the repository. The sandbox version is always shown first, and the repository version is second. Doppel performed the update shown in Example 3-13 and she needs to resolve the conflict before she commits this file.
Because CVS cannot merge binary files, a binary file for which both the repository and sandbox copies have changed since the sandbox copy was checked out always results in a conflict.
Adding Files to the Repository
Use cvs add to add a file or directory to the repository. Using cvs add on a file marks the file as needing to be added when cvs commit is run. Running cvs add on a directory adds the directory to the repository and the CVS subdirectory to the directory.
The Attic and CVSdirectoriesare special directories that CVS uses for its own purposes. Do not make a file or directory with these names.
If you attempt to commit and get an error message that includes *PANIC* administration files missing, you may have created a file or directory named CVS. This message means that CVS could not find the Repository file in the CVS subdirectory of the sandbox directory it is trying to commit.
You can use cvs remove to remove a file that has been added but not committed. This removes the marking in the CVS subdirectory and doesn't record the aborted addition in the repository's history. Similarly, you can use cvs add to abort a file removal; it will resurrect the file without recording the aborted removal.
The file or directory to be added must exist within the sandbox, and a directory must not contain a file or subdirectory named CVS.
Files and directories are case-sensitive in the repository. If you are using a CVS client or operating system that is not case-sensitive, you may encounter problems. Avoid using file or directory names that would be the same if case were not an issue.
In the process of adding a file, CVS strips trailing slashes and any special CVS files from the arguments, then checks for name conflicts (including some case-comparison testing). If CVS detects a name conflict, it notifies the user and does not add the file or directory.
cvs add uses the following syntax:
cvs [cvs-options] add [command-options] filename
The available options are -k, followed by any of the keyword flags, and -m, followed by an addition message. Keyword flags set default keyword-substitution modes. The most common keyword flag used with cvs add is -kb, used to add binary files. Any message specified using -m becomes the description message for the file (displayed in cvs log output) and is stored with the file when the file is committed. At least one filename must be used, and the file or directory to be added must exist.
Example 3-14 shows using cvs add to add directories and files.
Example 3-14. Using cvs add
bash-2.05a$ cvs add design plan design/*.rtf plan/*.rtf Directory /var/lib/cvs/wizzard/doc/design added to the repository Directory /var/lib/cvs/wizzard/doc/plan added to the repository cvs server: scheduling file `design/Analysis.rtf' for addition cvs server: scheduling file `design/Specification.rtf' for addition cvs server: scheduling file `plan/Schedule.rtf' for addition cvs server: use 'cvs commit' to add these files permanently
Removing Files from the Repository
The cvs remove command is used to mark a file as removed in the repository. The file isn't actually removed from the repository; it simply is stored in a special directory called Attic, so that its earlier revisions can be recalled. The file is no longer sent to sandboxes, and it is removed from existing sandboxes at the next cvs update, which displays the message cvs server: filename is no longer in the repository.
A removal must be committed before it affects the repository. If you notice that you accidentally removed a file you need (before you run cvs commit), you can use cvs add to undo the removal and then use cvs update to retrieve the removed file. This process leaves no record in the repository. Similarly, if a file has been added but not committed, cvs remove undoes the addition and leaves no record in the repository.
If someone else modifies a removed file before the removal is committed, the commit will fail and report a conflict. Resolve the conflict by unremoving the file with cvs add, checking the changes with cvs update or cvs diff, and removing the file again if desired. I strongly recommend speaking with the person who modified the file before you resolve such a conflict, lest you remove a file that should be retained.
To use cvs remove on a file, the file must not exist in the sandbox or you must call the cvs remove command with-f. Usually, I delete the file from the sandbox before running cvs remove.
The syntax for cvs remove is:
cvs [cvs-options] remove [command-options] filename
cvs remove has the following options:
- Delete the file from the sandbox.
- Perform a local, nonrecursive operation on this directory only.
- Perform recursive operation on all subdirectories as well as the current directory (default).
Example 3-15 shows a file being removed. Notice that the file is removed from the sandbox using the Unix rm command. Only then can you use cvs remove (unless you specify the -f option).
Example 3-15. Using cvs remove
bash-2.05a$ ls CVS main.c wizzard.h bash-2.05a$ rm main.c bash-2.05a$ cvs remove main.c cvs server: scheduling `main.c' for removal cvs server: use 'cvs commit' to remove this file permanently
cvs remove is affected by tags, and CVS cannot remove a file that has a sticky tag or a sticky date. Chapter 4 explains sticky tags and dates in detail. Here we will discuss only how they affect file removal.
When a file is retrieved using a tag name or a date, the file in the sandbox reflects the state of the repository at the time the tag or date occurred. Such files are not intended to be changed: they're only static representations of the past. This implies that such files can't be removed, either.
When you try to remove a nonremovable sticky-tagged file, CVS issues an error message such as the following: cvs server: cannot remove file `filename' which has a numeric sticky tag of`1.3'. Correct this error by using cvs update -A; then remove the file.
If a file has a nonbranch sticky tag, cvs remove removes the tag from the file in the sandbox. A comment in the code implies that this behavior may change in future, so if you wish to remove a sticky tag use cvs update -A instead of cvs remove.
Retrieving Removed Files
Retrieving a removed file is similar to retrieving a previous revision of a file. If you need to look at a file without making changes, use either:
cvs update -r revision
cvs checkout -r revision
If you need to make changes, there are three methods you can use to bring the removed file back into active service. Methods 1 and 2 are essentially the same, differing mostly in whether the file is added before or after the data is retrieved. Method 3 uses file merging to accomplish the task and should not be used on binary files.
Method 1 creates an empty file of the same name, uses cvs add to declare the file active, and then uses cvs update -j to replace the empty file with the file as it was just prior to the removal. The steps are as follows:
- Use touch filename to create a file of the specified name.
- Use cvs add filenameto make the name active again.
- Use cvs update -j revision with the revision number immediately before the deletion. This replaces the empty file with the file as it was prior to being removed.
If you choose the revision number that corresponds to the deletion, the following error message is returned: cvs server: `filename' is no longer in the repository.
- Use cvs committo commit the newly restored file to the repository.
Example 3-16 illustrates this method by retrieving main.c, which was previously removed using cvs remove.
Example 3-16. Retrieving a removed file, method 1
bash-2.05a$ touch main.c bash-2.05a$ cvs add main.c cvs server: re-adding file main.c (in place of dead revision 1.3) cvs server: use 'cvs commit' to add this file permanently bash-2.05a$ cvs update -j 1.2 main.c A main.c bash-2.05a$ cvs commit Checking in main.c;, 307C written /var/lib/cvs/wizzard/src/main.c,v <-- main.c new revision: 1.4; previous revision: 1.3 done
Method 2 uses cvs update to retrieve the file to stdout, sends stdout to a file of the same name as the removed file, and then uses cvs add to restore the file to the repository. The steps are as follows:
- Use cvs update -r previous_revision -p filename > filename, where previous_revision is the revision just before the file was removed.
- Use cvs add filename to make the name active again.
- Use cvs commit to commit the newly restored file to the repository.
Example 3-17 shows this method of retrieving a removed file.
Example 3-17. Retrieving a removed file, method 2
bash-2.05a$ cvs update -r 1.5 -p main.c > main.c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Checking out main.c RCS: /var/lib/cvs/wizzard/src/Attic/main.c,v VERS: 1.5 *************** bash-2.05a$ cvs add main.c cvs server: re-adding file main.c (in place of dead revision 1.6) cvs server: use 'cvs commit' to add this file permanently bash-2.05a$ cvs commit Checking in main.c;, 314C written /var/lib/cvs/wizzard/src/main.c,v <-- main.c new revision: 1.7; previous revision: 1.6 done
Method 3 merges the removed file with the unremoved file just before its removal. The steps are as follows:
- Use cvs update -j deletion_revision -j previous_revision filename. Be aware of the order of the -jarguments; it's important to put the revision number that refers to the deletion first.
- Usecvs commit to commit the newly restored file to the repository.
Example 3-18 shows this method of retrieving a removed file.
Example 3-18. Retrieving a removed file, method 3
bash-2.05a$ cvs update -j 1.8 -j 1.7 main.c U main.c bash-2.05a$ cvs commit Checking in main.c;, 323C written /var/lib/cvs/wizzard/src/main.c,v <-- main.c new revision: 1.9; previous revision: 1.8 done
CVS doesn't include any mechanism for removing directories from a repository. Any directory that contained files at a point in a project's history should be retained so that earlier revisions of the project can be retrieved.
If a directory is deprecated and its contents are no longer needed for the project, use cvs remove to empty the directory and its subdirectories of files other than the contents of the CVS subdirectory. To prevent these empty directories from being added to the sandbox, use the -P flag to the cvs update and cvs checkout commands. The -P flag instructs CVS not to download empty directories to the sandbox.
The -d command option to update and checkout brings down all directories that are in the repository but not the sandbox, including empty directories.
Use both -d and -P to bring down all nonempty directories.
To remove a directory that has never contained any files, or to remove any directory completely, you need to edit the repository, as described in Chapter 6.
Moving Files or Directories
There is no CVS command designed specifically to move a file or file directory. In fact, CVS's design doesn't accomodate such moves. However, you can work around this limitation using a combination of CVS commands, or by altering the repository using operating-system commands. Moving files can make project history difficult to track, because then a file's history is recorded across two different files in different locations. Minimize this potential source of confusion by recording the new and old locations with meaningful log messages.
To rename a file or directory at the operating-system level, move it from the old filename to the new filename. For example, use the Unix mv command.
The recommended way to move a file is to use cvs remove followed by cvs add, with messages that state where the file was moved from and to. This method preserves the file's history and allows reversion to earlier versions of the project in its old location. However, the messages stored with the add and remove commands are the only record of the move. Example 3-19 shows this method being used to rename the wizzard.hfile.
Example 3-19. Renaming a file
bash-2.05a$ mv wizzard.h config.h bash-2.05a$ cvs remove wizzard.h cvs server: scheduling `wizzard.h' for removal cvs server: use 'cvs commit' to remove this file permanently bash-2.05a$ cvs add config.h cvs server: scheduling file `config.h' for addition cvs server: use 'cvs commit' to add this file permanently bash-2.05a$ cvs commit . . . Moving src/wizzard.h to src/config.h CVS: --------------------------------------------------------------------- CVS: Enter Log. Lines beginning with `CVS:' are removed automatically CVS: CVS: Committing in . CVS: CVS: Added Files: CVS: config.h CVS: Removed Files: CVS: wizzard.h CVS: --------------------------------------------------------------------- . . . RCS file: /var/lib/cvs/wizzard/src/config.h,v done Checking in config.h; /var/lib/cvs/wizzard/src/config.h,v <-- config.h initial revision: 1.1 done Removing wizzard.h; /var/lib/cvs/wizzard/src/wizzard.h,v <-- wizzard.h new revision: delete; previous revision: 1.5 done
The recommended way to move a directory is to create and add the new directory. Use the technique described in the previous section to move all the files in the original directory to their new location, and use the -P flag for all checkouts and updates. By maintaining the old directory, previous releases of the project can be retrieved and the old copies of files that were in that directory are still stored in the repository.
Another way to move files or directories is to edit the repository directly. See Chapter 6 for methods and their advantages and consequences.
Releasing a Sandbox
The cvs release command should be used before you delete a sandbox. CVS first checks whether there are any files with uncommitted changes; then, if all is well, CVS runs cvs unedit on each file to signal that you no longer intend to edit the files, and writes to the history file in the repository to state that the sandbox was released. CVS also reports on files and directories that are not currently stored in the repository.
If there are uncommitted changes, CVS alerts you to the changes and does not release the sandbox. You can use cvs commit to commit the changes, remove the changed files manually, or use cvs update -A to revert to a state where you can release the sandbox (and lose the changed data).
It's not strictly necessary to use cvs releasebefore deleting a sandbox. You can delete a sandbox with no effect on the repository. However, if you get into the habit of using cvs release, you'll remember to use it the one time you do need to run an unedit or when you have made an uncommitted but important change.
The syntax for cvs release is:
cvs [cvs-options] release [-d] directory
The only option to cvs release is -d, which deletes the sandbox after checking it for uncommitted changes. You can use cvs release on an entire sandbox or on a subdirectory within the sandbox.
When you execute cvs release, you must specify a directory, but you can use a dot (.) to indicate your current working directory. Example 3-20 shows cvs release being used to release the wizzard sandbox. Note that a dot is used to specify the current working directory as the sandbox to release.
Example 3-20. Using cvs release
bash-2.05a$ cvs release . cvs server: warning: src/wizzard.h is not (any longer) pertinent ? src/test ? src/test.c U src/config.h U src/main.c You have  altered files in this repository. Are you sure you want to release directory `.': n ** `release' aborted by user choice.
As a response to the question Are you sure you want to release directory `directory', any line starting with Y or y is considered to be a yes; any other initial character is considered to be a no.
CVS recognizes keywords that can be included in any source file other than a binary file. When CVS finds a keyword in a file it is checking out, it expands the keyword to provide metadata about the latest revision of the file. CVS keywords take the following form:
Example 3-21 shows a file that includes CVS keywords.
Example 3-21. CVS keywords
# Makefile for the Wizzard project # First created by J Vesperman, 1 September 2002 # # Current revision $Revision: 1.6 $ # On branch $Name: $ # Latest change by $Author: chodacki $ on $Date: 2004/04/16 16:15:52 $ # Initial declarations CC=gcc SUBDIRS = man doc src lib # Declaring phony targets .PHONY: all clean install all: wizzard echo "all: make complete" clean: rm -f src/*.o rm -f wizzard echo "clean: make complete" . . . # Log record for Makefile changes: # $Log: ch03.xml,v $ # Revision 1.6 2004/04/16 16:15:52 chodacki # sfcleanup fixes # # Revision 1.5 2003/07/11 20:00:23 madd # madd final SC edits # # Revision 1.4 2003/07/09 21:31:56 madd # madd SC edits # # Revision 1.3 2003/07/07 21:52:50 madd # madd SC edits # # Revision 1.2 2003/06/27 21:47:43 madd # madd R2 conversion edits # # Revision 1.1 2003/06/26 22:22:10 madd # Initial revision #
Example 3-22. Expanded keywords
# Current revision $Revision: 1.6 $ # On branch $Name: $ # Latest change by $Author: chodacki $ on $Date: 2004/04/16 16:15:52 $ # Initial declarations CC=gcc SUBDIRS = man doc src lib . . . # Log record for Makefile changes: # $Log: ch03.xml,v $ # Revision 1.6 2004/04/16 16:15:52 chodacki # sfcleanup fixes # # Revision 1.5 2003/07/11 20:00:23 madd # madd final SC edits # # Revision 1.4 2003/07/09 21:31:56 madd # madd SC edits # # Revision 1.3 2003/07/07 21:52:50 madd # madd SC edits # # Revision 1.2 2003/06/27 21:47:43 madd # madd R2 conversion edits # # Revision 1.1 2003/06/26 22:22:10 madd # Initial revision # # Revision 1.2 2002/09/01 06:57:23 jenn # Initial code in the Makefile.
The full list of possible keywords is provided in Chapter 11. These are the most commonly used keywords:
- The username of the user who committed the last revision.
- The date on which the last revision was committed, in UTC.
- A header that contains information about the file, including the author, date and revision number, pathname of the RCS file, file status, and whether the file is locked. See Chapter 5 for information about file locking.
- The tag name the file was checked out with. This keyword can display a branch or provide a more meaningful identification of a revision than the revision number alone. See Chapter 4 for more information about tags and branches.
In CVS 1.11.5, the Name keyword is updated only on a fresh checkout, and displays only static tags. This problem may be corrected in a later version.
- Commit messages, dates, and authors, recorded in the file itself. Any characters that prefix the keyword are also used to prefix log lines; this enables comment markers to be included automatically. Unlike most keywords, existing log expansions are not overwritten with the new ones; the new ones are merely prepended to the list.
The cvs log command displays all the information that the Logkeywordprovides.
The Log keyword is best used at the end of a file, to avoid users having to go through all the log messages to get to the important parts of the file.
The log created by the Log keyword does not merge neatly when CVS merges a branch back to the trunk. If it is likely that your file will be branched and remerged, it is better to use the cvs log command than to store a log within the file.
- The CVS internal revision number of the file. This number is specific to the individual file and does not identify a stage within the project.
Do not edit keyword expansions. CVS will change them automatically each time a file is checked out. Altering the format or syntax of an expansion may make it unrecognizable to CVS.
Resist the urge to edit the data stored in the Log expansion.Doing so means that it will differ from the output of the cvs logcommand, which will create doubt about who actually did what, and when.
Keyword expansion can be modified when using the admin, add, checkout, export, and update commands. Options to admin and add modify the default keyword-expansion mode of a file. Options to checkout, export, and update modify the keyword-expansion mode of the current sandbox version of a file, overriding the file's default mode. When checkout and update create or modify a sandbox, they can set a keyword-expansion mode to apply to the copy of a file in that sandbox. Some commands (such as diff ) have temporary keyword-expansion modes that apply while the command is running.
Keyword-expansion modes are set with -k or -A flags to the relevant command. These are the most common modes:
- Inhibit keyword expansion and line-ending conversion. Use this keyword-expansion mode to signal that a file is binary.
CVS can convert line endings from the form appropriate to the server to the form appropriate to the client. Line-ending conversion can corrupt binary files.
- Generate only the keyword name, not the name and the value. Use this mode when merging different (nonbinary) versions of a file, to prevent keyword substitution from creating spurious merge errors.
- Generate the version of the keyword string that was present just before the file was last committed, rather than as it should be with the modifications of the last commit. This mode is similar to the effect of -kb, but with line-ending conversion.
- Generate only the value of the keyword, rather than the name and value. This mode is most useful with cvs export, but do not use it for binary files. Once a keyword name is removed from a file, further expansions are not possible unless the word is replaced.
- Reset all sandbox-specific dates, tags, and keyword-expansion modes to the file's defaults, and retrieve the latest revision (the revision at the head of the trunk). This mode is used only for checkout and update.
Binary Files and Wrappers
The default CVS method of handling file conflicts works well for text files, because CVS can determine which lines have changed and add or remove them as appropriate. It doesn't work well on binary files, because such files are not usually built around lines of text separated by carriage returns.
Some files with textual content are not actually text files. Files such as those created by Microsoft Word or OpenOffice should be flagged as binary, because line-by-line merging and keyword expansion could damage the saved data.
CVS doesn't work for device files, symbolic links, or other files that cannot be modified and moved. Rather than trying to store these files in CVS, include the commands to create or connect them in your build scripts.
For binary files, CVS uses a different method of conflict resolution. The two methods CVS has available are MERGE and COPY. MERGE is the default CVS method. COPY instructs CVS to provide the user with both versions of the file if there is a conflict, so the user can blend the changes manually and recommit.
Binary files should be added to CVS using the -kb command option to cvs add. If the expansion mode is not set at the time the file is added, the -kb command option to cvs admin will set the mode retroactively. This informs CVS not to expand keywords, not to modify line endings, and to use the COPY method of conflict resolution. Example 3-23 shows the use of these command options.
Example 3-23. Setting keyword expansion for binary files
bash-2.05a$ cvs add -kb Requirements.doc cvs server: scheduling file `Requirements.doc' for addition cvs server: use 'cvs commit' to add this file permanently bash-2.05a$ cvs add AcceptanceTest.doc cvs server: scheduling file `AcceptanceTest.doc' for addition cvs server: use 'cvs commit' to add this file permanently bash-2.05a$ cvs commit . . . bash-2.05a$ cvs admin -kb AcceptanceTest.doc RCS file: /var/lib/cvs/wizzard/doc/design/AcceptanceTest.doc,v done
The flag to cvs addworks well on a file-by-file basis, but when you need to add or import a large set of files, setting each binary file's expansion mode manually is annoying. CVS wrappers allow you to control the merge methodology or keyword-substitution modes used on a file, based on the filename (usually specified by the file extension). When a file matches a wrapper, the merge method or substitution mode in the wrapper is used instead of the method otherwise used in the command.
Wrappers can be specified using the -W command option for updateand import, in the .cvswrappers file in the user's home directory on the client machine, or in the cvswrappers file in the repository's CVSROOT subdirectory.
The CVSWRAPPERS environment variable is read, but code comments imply that its behavior may change. The code currently reads one wrapper from this environment variable. If you are using a version of CVS later than 1.11.2, check the documentation to see whether multiple wrappers are read.
To specify a wrapper in a .cvswrappers or cvswrappers file, use the following syntax:
wildcard option value [option value...]
Specify a wrapper using the -Wcommand option as follows:
-W "wildcard option value"
In the files, use one wrapper per line.
When using wrappers on the command line, use the shell escape character to escape any symbols that your shell tries to expand.
These are the available wrapper options:
- Indicates the merge methodology to be used for files that match the pattern. The values for -m are COPY or MERGE, described earlier in this section.
- Indicates the keyword-expansion mode to be used for files that match the pattern. The values for -k are the keyword-substitution modes explained in Section 3.10 in this chapter, without the -k prefix. For example, the value that indicates the binary-file mode is b, not -kb.
Replace wildcard in the wrapper syntax with a regular expression for pattern matching. Chapter 11 provides a full explanation of CVS pattern matching. These are the most important of the special symbols:
- Matches any string, including the empty string
- Matches any single character
Example 3-24 shows a cvs update using a wrapper parameter. (Note that I use the shell escape character for the bash shell to escape the asterisk.)
Example 3-24. Using cvs update with wrappers
bash-2.05a$ cvs update -W"Ma\* -k 'v'" cvs server: Updating . U Makefile cvs server: Updating doc cvs server: Updating doc/design cvs server: Updating doc/plan cvs server: Updating lib cvs server: Updating man cvs server: Updating src bash-2.05a$ less Makefile # # Makefile for the Wizzard project # First created by J Vesperman, 1 September 2002 # # Current revision 1.3 # On branch # Latest change by jenn on 2002/09/12 12:57:40
Upgrade to at least CVS 1.10 before using wrappers to signal binary files. In CVS 1.9 and earlier, the COPY option of a wrapper overwrites a file rather than providing two versions.
Specifying Default Command Options
If you find yourself regularly using the same options with a command, you can use the .cvsrc file to set default options and minimize your typing. If the .cvsrc file is in your home directory on your client machine, CVS will read the file, look for the CVS command you are currently running, and will run the command with the options specified for that command in the file. To temporarily avoid parsing the .cvsrcfile, use the -fCVS option.
The .cvsrc file format is one line per command. Start a line with the command you want to modify, followed by the options you want as the default. You can also specify default CVS options in the .cvsrc file. To do so, use cvs as the command.
Example 3-25 shows a .cvsrcfile. This file specifies a default description for adding files, specifies (using -P) that update and checkout prune empty directories, and specifies (using -q) that CVS run quietly, but not as quietly as it would with the -Q option.
Example 3-25. A .cvsrc file
add -m "Part of the wizzard project" update -P checkout -P cvs -q
- ↑ See Chapter 10 for a full list of CVS options.
- ↑ checkout is similar to update -d if it is called from the directory in the sandbox that corresponds to the project parameter given to checkout. If it is called from a different directory, it checks out a new sandbox based in the current working directory.
- ↑ See Chapter 5 for commands that show recent changes.
- ↑ The cvs unedit command is explained in Chapter 5. The history file is explained in Chapter 7.