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 commit when 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.
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:
The file has been added to the sandbox, but it has not been committed.
There is a conflict between the repository copy and the sandbox copy; this conflict requires human intervention to resolve.
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.
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.
The file has been removed from the sandbox, but it has not been committed.
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.
The file is in the sandbox but not the repository, and it is not marked for addition to the repository.
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).
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 -A if 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).
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.
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.
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.
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: 188.8.131.52 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.
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.
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.
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 update to write the 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 -p option. The less command shows the contents of the file after the reversion.
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 commit after retrieving with either method adds the current contents of the sandbox file (identical to the old revision) to the repository as the newest revision.
The -D option 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.
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.
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. */
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.
 See Chapter 5 for commands that show recent changes.
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.
Merging is done during cvs update, but it can also occur when checkout is used on an existing sandbox. Example 3-6 showed a merge during an update. Example 3-12 shows both a merge and a conflict.
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.
<<<<<<< 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.