MIT Information Systems

Macintosh Development

[Home] [About Us] [People] [Information Systems]
[Kerberos for Macintosh] [Applications] [Miscellaneous Documentation]


Working With CVS

A guide to CVS operation and basic CVS commands

by Miro Jurisic

This is not a complete CVS reference. Less frequently used options and commands are not listed. For a complete CVS reference, please use the CVS manual.

CVS commands in general

If you need to use a CVS command for which MacCVS does not have a menu equivalent, you will need to type in the command line for it in MacCVS. Also, you might need to use CVS from a UNIX workstation. Therefore, you need to be familiar with the general structure of CVS commands and their options.

Each CVS command line consists of 5 parts:

cvs <global options> <command name> <command options> <files>

Since all parts of a CVS command line are space-separated, each file or folder path that contains a space must be enclosed in quotes.

Global CVS options

-d cvsroot
Overrides the CVSROOT in your MacCVS preferences. See also () for more information.
-H
Displays brief help for the command (for example cvs -H checkout). With no command name, displays global CVS help.
-q
Overrides the 'quiet' setting in your MacCVS preferences, and causes MacCVS to be somewhat quiet.
-z compression-level
Sets the gzip compression level for network traffic (1 to 9). The 'Enable TCP/IP Compression' setting corresponds to -z9

Repository

When a CVS command is being executed on a file, CVS needs to determine the repository location of the file. In most cases, this information will be retrieved from the Repository and Root files, contained in the CVS folder which is in the same folder as the file the command is working on. However, some commands do not operate on working files (most notably checkout and import) and therefore need to know the repository path from some other source. On UNIX, this is the CVSROOT environment variable; in MacCVS this is the CVSROOT setting in your preferences.

If you want to temporarily change your CVSROOT (for example, to import something in to a repository which is not your the CVSROOT in your preferences), you can use the global -d option.

It follows from the way CVS works that you do not have to change your CVSROOT when you are switching among working files from different repositories, unless you are using checkout or import, since the information stored in the CVS folder on each level of your working files will always take precedence over your settings.

Sticky options

Sticky options are options associated with a particular working file or folder that are persistent until you explicitly change them. For example, if you checkout a project by date, the date becomes a sticky option, so that even if you run update on those working files, they will not be updated to the most recent version; they will be 'stuck' to that date until you reset the sticky options (for example, using update -A).

This can be useful if you want to have several different versions of a single project (for example, from several different branches), and still be sure that they will all be updated appropriately.

You can view all sticky options on a file by running the CVS status command on it.

Keyword substitution

CVS uses a mechanism known as keyword substitution (or keyword expansion) to replace strings of the form $Keyword$ with strings of the form $keyword:value$ every time you obtain a new revision of a file. In most cases, you will leave the keyword substitution mode at its defaults for all text files, and you will set keyword substitution mode to kb for binary files. You can do this when adding the file, and there is rarely a need to change this afterwards.

The full list of CVS keywords and their expansions is in the CVS manual.

Date specifications

Some CVS commands take a date and a time as a part of an option. CVS understands a wide variety of date formats, including:

in the form 3/31/92 are always in month/day/year format.


Checkout

The checkout command is used to create a new set of working files for some project. For example, if you are working on the TestTrack library, and you want to have two versions of it on your development machine (for example, you might want to have the current version and an older version checked out by date), you would use checkout to create the first one, and then use checkout again to create the second one.

Another example where you would need to use checkout is if you have checked out the entire macdev repository and now you want to build Kerberos v5 library. You would then checkout Kerberos v5 into some folder among your macdev working files.

You should not use checkout to get new copies of files in a project you are already working on. If, for example, you make changes to a file, and decide to discard them, you can move the file to the trash and then use the update command to get a new copy of the file.

As a rule of thumb, you should use checkout only once on a file or a folder, when you first start working with it. Afterwards, you should always use the update command to get an up-to-date copy of that file or folder.

Because of the way the checkout command works, it's easier to use the update command than the checkout command to get the initial copy of a folder, if you already have checkout out its parent folder (this can happen, for example, if you checkout a folder and then someone else creates a new folder inside it). Refer to the section about the update command for more details about this.

Checkout options

-D date
Use the most recent revision no later than date. This option is sticky, and implies -P option.
-r tag
Use revision tag tag. This option is sticky.
-f
only useful with -D and -r: if no matching revision is found, retrieve the most recent repository revision (instead of ignoring the file).
-l
Do not recurse into subdirectories
-P
Prune empty directories
-p
Write the files to the console instead of saving them to disk
-j
Merge changes from a branch and the trunk, or from two branches, into the working directory. See the section about merging for more information.

Checkout examples

Get a copy of the MacMoira project:

cvs checkout mit/appl/MacMoira

Get a copy of MacMoira as it was a day ago:

cvs checkout -D yesterday mit/appl/MacMoira


Commit

The commit command is used to commit the changes you made to files. By default, it recurses into folders, so committing a folder will cause all files and folders it contains to be recursively committed. Only files that have been modified will be committed and given a new revision in the repository.

Commit options

-l
Local; disables recursion
-R
Recurse into subfolders (on by default)
-r tag
Commit to branch with tag tag.
-m message
Use message as the log message.

Commit examples

Creating a new branch from the sources in your working files:

cvs tag -b New_Branch
cvs update -r New_Branch
cvs commit

It is extremely important that you run the update command if you are creating a new branch from your working files, because otherwise any files that you add after committing would not be put on the correct branch. Since branch tags are sticky, the commit command will run with -r New_Branch, so that the changes will be committed correctly if you use update.


Update

The update command should be used to update your working files and folders to their latest repository versions. You should use the update command to get a new copy of a file that you deleted, or to get a new copy of a folder whose parent folder you already have among your working folders.

Update options

-D date
Use the most recent revision no later than date. This option is sticky, and implies -P option.
-r tag
Use revision tag tag. This option is sticky.
-f
only useful with -D and -r: if no matching revision is found, retrieve the most recent repository revision (instead of ignoring the file).
-l
Do not recurse into subdirectories
-P
Prune empty directories
-p
Write the files to the console instead of saving them to disk
-j
Merge changes from a branch and the trunk, or from two branches, into the working directory.
-A
Reset all sticky options. This will cause all sticky options on all updates files to be restored to their repository values: date and branch tags will be removed, and keyword substitution mode will be set to the keyword substitution mode the files have in the repository

Update examples

Updating sources to their day-old versions:

cvs update -D yesterday

Updating sources to their most recent revisions from a branch:

cvs update -r The_Branch

Resetting sticky options (therefore updating the sources to their most recent trunk versions):

cvs update -A

Getting a copy of MacMoira folder (assuming you don't have one already)

cvs update -d MacMoira

Merging branches

Merging from branch into trunk

Merging changes from a branch into the trunk is slightly complex, because you need to tag the branch before merging it with the trunk (unless you are certain that you will merge the branch into the trunk only once). first, you should commit your sources, regardless of whether you are working in the trunk or on the branch:

cvs commit

Next, if you are working in the trunk, you need to get to the branch so you can tag it. If you are already working on the branch, you don't nees to do this:

cvs update -r The_Branch

Then you tag the branch:

cvs tag Merged_The_Branch_Into_Trunk_14121997

The tag should be unique, since you might later want to merge from the branch into the trunk again; a simple way to make the tag unique is to include the branch name and the date in it (assuming you don't merge twice in the same day).

After the branch is tagged, you update to the trunk sources:

cvs update -A

Now you are ready to merge the branch and the trunk. If this is the first time you are merging, you should use:

cvs update -j The_Branch

Otherwise, you need to specify the tag you used the last time you merged that branch into the trunk (which you can determine using cvs log):

cvs update -j Merged_The_Branch_Into_Trunk_10101997 -j The_Branch

The order of -j options is important; the first one should be the tag youused the last time you merged the branch into the trunk, the second one the branch tag.

Of course, you might encounter merge conflicts that you will need to resolve before committing.

Merging from the trunk into a branch

The procedure for merging from the trunk into a branch is similar to the one for merging from a branch into the trunk. First, you commit your sources:

cvs commit

Next, you need to get and tag the trunk sources:

cvs update -A

cvs tag Merged_Into_The_Branch_14121997

The tag should be unique, since you might later want to merge from the branch into the trunk again; a simple way to make the tag unique is to include the branch name and the date in it (assuming you don't merge twice in the same day).

Now, get the branch sources:

cvs update -r The_Branch

If this is the first time you are merging into the branch, you should use

cvs update -j Merged_Into_The_Branch

to merge the sources. Otherwise, you need to specify the tag you used the last time you merged into the branch:

cvs update -j Merged_Into_The_Branch_10101997 -j Merged_Into_The_Branch_14121997

The order of -j options is important; the first one should be the tag of the last time you merged, the second one the tag you used to tag the revision of trunk sources you are about to merge.

You might encounter merge conflicts you need to resolve before you can commit your merged sources.


Add

To add files or folders to the repository, you should use the add command. The add command only schedules files for addition; you still need to commit them for them to actually be added to the repository.

Add options

-k option
Sets the keyword substitution for file to option. See the section on keyword substitutions for more information

Add examples

Add a file as binary:

cvs add -kb source.c


Remove

To remove files from the repository, you should use the remove command. The remove command only schedules files for removal; you still need to commit them before they will be marked as removed in the repository.

Remove examples

Remove a file:

cvs remove source.c


Status

To get the status of a working file (or all files in a working folder), you can use the status command. The status command will display output of the following form:

===================================================================
File: checkoutlist       Status: Up-to-date
 
   Working revision:    1.1
   Repository revision: 1.1     /cvs/macdev_test/CVSROOT/checkoutlist,v
   Sticky Tag:      (none)
   Sticky Date:      (none)
   Sticky Options:   (none)

The first line of the output contains the name of the file and one of the following status indicators:

Up-to-date
The file is identical with the latest revision in the repository for the branch in use.
Locally Modified
You have edited the file, and not yet committed your changes.
Locally Added
You have added the file with add, and not yet committed your changes.
Locally Removed
You have removed the file with remove, and not yet committed your changes.
Needs Checkout
Someone else has committed a newer revision to the repository. The name is misleading; you will ordinarily use update rather than checkout to get that newer revision.
Needs Patch
Like Needs Checkout, but the CVS server will send a patch rather than the entire file. Sending a patch or sending an entire file accomplishes the same thing.
Needs Merge
Someone else has committed a newer revision to the repository, and you have also made modifications to the file.
Unresolved Conflict
This is like Locally Modified, except that a previous update command gave a conflict. You need to resolve the conflict.
Unknown
CVS doesn't know anything about this file. For example, you have created a new file and have not run add.

Working revision lists the revision of the working file (which is the repository revision at the time you last updated the file). Repository revision lists the current repository revision and the full path to the history information on the server.

Sticky tag, date, and options show the sticky options for the working file. You can reset them using cvs update -A.

Status options

-l
Local: do not recurse into subdirectories.
-v
Verbose: display additional information about each file: all symbolic tags along with revision numbers they correspond to.

Status examples

Get status of all files in a folder (recursing into subfolders)

cvs status

Get status of all files in a folder (no recursing)

cvs status -l

Get detailed status of source.c

cvs status -c source.c


Log

To get a full log of all the changes made to a file since it was created, or log of changes made to a file over a specified period of time, you need to use the log command.

Log options

-l
Do not recurse into subdirectories
-N
Do not print the list of symbolic tags (useful if the file has many tags and you are not interested in them)
-h
Do not print the log entries
-wusernames
Print information about revisions committed by users with usernames in the comma-separated list usernames. If no usernames are specified, the user's username is assumed.
-d dates
Print only information about revisions matching the date specification in dates. Date specifications can be the standard CVS date specifications, or a range formed from the standard CVS specification according to the following rules:
d1<d2
All dates between d1 and d2
d1<
All dates after d1
d1>
All dates before d1
d
The most recent revision older than d

Multiple ranges can be used inside one date specification by separating them with semicolons. Using <= and >= instead of < and > indicates that the ranges are inclusive.

-r revisions
Print only information about the comma-separated list of revisions and ranges. Ranges can be specified with:
rev1:rev2
revisions rev1 to rev2 (rev1 and rev2 must be on the same branch)
:rev
revisions from the beginning of the branch up to and including rev
rev:
revisions from rev to the end of the branch containing rev
branch
a branch revision means all revisions on that branch
branch1:branch2
a range of branches means all revisions on all branches in that range
branch.
the latest revision on branch

A bare -r with no arguments means the most recent revision on the default branch (usually the trunk).

Log examples

All revisions on branch The_Branch since yesterday you committed:

cvs log -w -r The_Branch -d yesterday<


Diff

The diff command is used to display the differences between revisions of files. The default behavior is to compare your working file with the most recent repository revision, but you can optionally compare your working file to an arbitrary revision of the file, or compare two arbitrary revisions of the file to each other.

Diff options

-l
Do not recurse into subdirectories
-D date
Compare to most recent revision dated no later than date
-r tag
Compare with revision tag.
-c
Contextual diff (displays more useful diff output)

You can use zero, one, or two -r or -D options, for no more than two total. If you use zero, diff will compare your working file with the most recent repository version. If you use one, the working file will be compared with the specified repository revision. If you use two, or one of each, the two specified files will be compared.

Diff examples

Contextual diff of source.c working file and it's version from a day ago

cvs diff -c -D yesterday source.c


Questions or comments? Send mail to macdev@mit.edu
Last updated on $Date: 2003/11/18 21:58:31 $
Last modified by $Author: smcguire $