Labeling and Branching

a part of MarkD's Guide to CVS


Labeling happens when a symbolic name is associated with a set of revisions, one particular revision per file. Labels, also known as tags, are used to identify which revisions are part of a logical unit, say a particular version of a software project or the files that make a set of patches for some other project.

Creating Labels

CVS has two commands, cvs tag and cvs rtag for creating and manipulating labels. cvs tag uses a directory hierarchy in the file system to determine which revisions to associate with the label, while cvs rtag works directly on the repository.

To create a label using cvs tag, perform these steps:

  1. % cd your-project-directory
  2. % cvs update
    And look at the output. Make sure there are no locally modified files or unknown files. Commit or add files as appropriate.
  3. % cvs tag -R tag-name
For example, to tag the photonet-dev directory for ACS 2.5
% cd /web/photonet-dev
% cvs update
% cvs tag -R acs-2.5

Checking Out Based on a Label

  1. % cd someplace to check out to
  2. % cvs checkout -r tag-name project-name
or more concretely:
% cd /web
% cvs checkout -r acs-2.5 acs

note You don't want to do this if there already was a /web/acs. This would wipe out what was already there.

You can specify the -d argument to cvs checkout to have the checkout happen in a new directory:

% cd /web
% cvs checkout -d somedirectory -r acs-2.5 acs
Which would check out the revisions labeled with "acs-2.5" and put them in a directory hierarchy rooted at /web/somedirectory

Also note that this checks out a tree with "sticky" labels (more on this in the branching section), so you won't be able to check in new revisions of files. Usually, this isn't a big deal, since you'll be checking out versions of the project that was made at a well-defined moment, and you don't want to be changing the revisions pointed to by the labels willy-nilly.

Manipulating Labels

The main manipulation you'd be doing on a label is changing the revision number for a particular file. Say for instance that you tagged revision 1.5 of subject.tcl with a label, and then you realized that subject.tcl should really have been revision 1.6. To change the label, do this:
  1. % cd directory-of-the-file-to-change
  2. % cvs tag -F -r revision-number tag-name file-name
The "-F" stands for "force" a tag. A concrete example is:
% cd /web/photonet-dev/www/bboard
% cvs tag -F -r 1.6 acs-2.5 subject.tcl

Deleting Labels

You can delete labels once you're done with them. Development labels, and labels for beta versions of products are usually pretty safe to get rid of. You'll want to hang on to labels for released versions of products for support and maintenance purposes.
  1. % cvs rtag -d tag-name project-name
% cvs rtag -d acs-2.5 acs
Note that cvs rtag is being used, since we're really just battering the repository to delete a tag rather than involve a specific set of files.


Branching in CVS can be a black art. You think you've performed the proper magic, and yet things Aren't Working Correctly. If you mess up something, don't worry. You're not the first.

Kinds of Tags

CVS has two different kinds of tags. "Sticky" tags which are tightly bound to one particular revision number for a given file, and "Branch" tags that allow you to check in new revisions. You can check out a source tree using a sticky tag or a branch tag. If you try to check in a revision on a sticky tag tree, you'll be rebuked with an error. One thing that complicates the tagging process is that you can change a particular directory between tags, so you can treat it as a sticky tagged directory, perform an operation, then treat it as a branch tagged directory.

Creating a Branch Tag

There's two ways of making a branch tag. One is using an existing file hierarchy to define which revisions of the files to use (which is handy for making a development/exploration branch) ,and the other is to base a branch tag off of an existing tag (which is handy for making a maintenance branch off of a sticky tag for a released version of a product).

To create a branch tag based on an existing hierarchy:

  1. % cd your-project-directory
  2. % cvs tag -R -b tag-name
note the addition of the "-b" option. For those of you who like examples:
% cd /web/photonet-dev
% cvs tag -R -b acs-2.5
To create a branch tag using an existing tag:
  1. % cvs rtag -r existing-tag-name -b branch-tag-name project-name
which would look like this in the real world:
% cvs rtag -r acs-2.5 -b acs-2.5-maintenance acs

Checking Out Based on a Branch Tag

Just like you do with a sticky tag:
  1. % cd someplace to check out to
  2. % cvs checkout -r tag-name project-name
or more concretely:
% cd /web
% cvs checkout -r acs-2.5 acs
Unlike when checking out with sticky tags, you can modify files and check them in. They'll end up in their branch.

Reorienting Your Development Tree

Say you have a directory hierarcy you checked out using a sticky tag. You notice that there are errors, or that you need to fix something. You make your changes, check in your changes, and get this:
cvs commit: sticky tag `acs-2.5' for file `rolf-np.tcl' is not a branch
cvs [commit aborted]: correct above errors first!
Rather than re-checking out a directory hierarchys based on a branch tag and copying your files over, you can "point" your development tree to a different label without losing your work:
  1. % cd your-project-directory
  2. % cvs update -r tag-name
So, if you wanted to point your directory hierarchy to the ACS 2.5 maintenance branch label, you'd do this:
% cd /web/acs-25
% cvs update -r acs-2.5-maintenance
And to point your directory hierarchy to the ACS 2.5 sticky label, you'd do this:
% cd /web/acs-25
% cvs update -r acs-2.5
and to point your directory hierarchy to the head revision (a.k.a. the tip of the revision tree)
% cd /web/acs-25
% cvs update -A

Merging Between Branches

CVS can do automatic merging between branches of a revision tree, and it's surprisingly good at it. The "-j" option of cvs update is what triggers the merging. I've not used this facility in quite a while, so I won't give examples right now, lest I really cause someone to screw things up.
$Id: labeling-n-branching.html,v 1.2 1999/12/23 21:49:10 markd Exp $