3.4. 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 commit when you have changed sandbox files since your last commit; use cvs update when you know that the repository has been changed since you last updated, or when you wish to check whether it has changed.
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. Figure 3-6 shows Cervisia immediately after an update.
Example 3-6. Using cvs update
Figure 3-6. Update with Cervisia
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:
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:
Tags and stickiness are explained in Chapter 4. Wrappers and keywords are explained later in this chapter.
3.4.1. 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. Figure 3-7 shows a log display from the TkCVS graphic client.
Example 3-7. cvs log output
Figure 3-7. Log output from TkCVS
This chapter discusses 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.
220.127.116.11. 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 with the copy it retrieves from the repository, and places the merged file in your sandbox. See "Conflicts and Merging," later in this chapter.
If you make changes to a static revision and want to commit the changed file to the repository as a new revision (but losing any changes made between the static revision and the current repository 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. Figure 3-8 shows retrieval by tag in Cervisia.
Example 3-8. Retrieval by revision number
Figure 3-8. Retrieval by tag in Cervisia
18.104.22.168. Reverting changes
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. If you have any changes in the sandbox made since the sandbox_revision was last committed, those changes are preserved; if you want to get rid of those changes as well, remove the file before you run this command, or use -C, as explained earlier in this section.
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
You can also revert to a previous revision of a file with the following command:
cvs update -r revision -p filename > 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. This method overwrites the file in the sandbox: any changes you've made to it that haven't been committed to CVS will be irretrievably gone.
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.
Example 3-10. Reverting changes with update -r -p
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.
22.214.171.124. Retrieving by date
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 datethe 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 April 2006. Note the use of -C, as for retrieving by revision.
Example 3-11. Retrieving with update -D
3.4.2. When to Update
Update frequently. Always update before beginning workperhaps first thing in the morning and just after lunch. This habit 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 that person immediately (see Chapter 5 for commands that show recent changes). Frequent commits and updates catch these problems early.
3.4.3. 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.
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.
Example 3-12. File merge and conflict during update
If a line in the repository copy is different from 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. Figure 3-9 shows the conflict resolution display in TkCVS.
Example 3-13. Conflicts in a file
Figure 3-9. Conflicts in TkCVS
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, you'll always get a conflict if a binary file has been changed in the repository and the sandbox copy has also been changed since it was checked out.
More detailed examples of conflict resolution and merging are given in Chapter 4.