Go to the previous, next section.

Branches

So far, all revisions shown in this manual have been on the main trunk of the revision tree, i.e., all revision numbers have been of the form x.y. One useful feature, especially when maintaining several releases of a software product at once, is the ability to make branches on the revision tree. Tags, symbolic names for revisions, will also be introduced in this chapter.

Tags--Symbolic revisions

The revision numbers live a life of their own. They need not have anything at all to do with the release numbers of your software product. Depending on how you use CVS the revision numbers might change several times between two releases. As an example, some of the source files that make up RCS 5.6 have the following revision numbers:

ci.c            5.21
co.c            5.9
ident.c         5.3
rcs.c           5.12
rcsbase.h       5.11
rcsdiff.c       5.10
rcsedit.c       5.11
rcsfcmp.c       5.9
rcsgen.c        5.10
rcslex.c        5.11
rcsmap.c        5.2
rcsutil.c       5.10

You can use the tag command to give a symbolic name to a certain revision of a file. You can use the `-v' flag to the status command to see all tags that a file has, and which revision numbers they represent. (The output of status unfortunately uses the word "version" instead of "revision".)

The following example shows how you can add a tag to a file. The commands must be issued inside your working copy of the module. That is, you should issue the command in the directory where `backend.c' resides.

$ cvs tag release-0-4 backend.c
T backend.c
$ cvs status -v backend.c
===================================================================
File: backend.c         Status: Up-to-date

    Version:            1.4     Tue Dec  1 14:39:01 1992
    RCS Version:        1.4     /usr/local/cvsroot/yoyodyne/tc/backend.c,v
    Sticky Tag:         (none)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        release-0-4                     (revision: 1.4)

There is seldom reason to tag a file in isolation. A more common use is to tag all the files that constitute a module with the same tag at strategic points in the development life-cycle, such as when a release is made.

$ cvs tag release-1-0 .
cvs tag: Tagging .
T Makefile
T backend.c
T driver.c
T frontend.c
T parser.c

(When you give CVS a directory as argument, it generally applies the operation to all the files in that directory, and (recursively), to any subdirectories that it may contain. See section Recursive behavior.)

The checkout command has a flag, `-r', that lets you check out a certain revision of a module. This flag makes it easy to retrieve the sources that make up release 1.0 of the module `tc' at any time in the future:

$ cvs checkout -r release-1-0 tc

This is useful, for instance, if someone claims that there is a bug in that release, but you cannot find the bug in the current working copy.

You can also check out a module as it was at any given date. See section checkout options.

When you tag more than one file with the same tag you can think about the tag as "a curve drawn through a matrix of filename vs. revision number." Say we have 5 files with the following revisions:

        file1   file2   file3   file4   file5

        1.1     1.1     1.1     1.1  /--1.1*      <-*-  TAG
        1.2*-   1.2     1.2    -1.2*-
        1.3  \- 1.3*-   1.3   / 1.3
        1.4          \  1.4  /  1.4
                      \-1.5*-   1.5
                        1.6

At some time in the past, the * versions were tagged. You can think of the tag as a handle attached to the curve drawn through the tagged revisions. When you pull on the handle, you get all the tagged revisions. Another way to look at it is that you "sight" through a set of revisions that is "flat" along the tagged revisions, like this:

        file1   file2   file3   file4   file5

                        1.1
                        1.2
                1.1     1.3                       _
        1.1     1.2     1.4     1.1              /
        1.2*----1.3*----1.5*----1.2*----1.1     (--- <--- Look here
        1.3             1.6     1.3              \_
        1.4                     1.4
                                1.5

What branches are good for

Suppose that release 1.0 of tc has been made. You are continuing to develop tc, planning to create release 1.1 in a couple of months. After a while your customers start to complain about a fatal bug. You check out release 1.0 (see section Tags--Symbolic revisions) and find the bug (which turns out to have a trivial fix). However, the current revision of the sources are in a state of flux and are not expected to be stable for at least another month. There is no way to make a bugfix release based on the newest sources.

The thing to do in a situation like this is to create a branch on the revision trees for all the files that make up release 1.0 of tc. You can then make modifications to the branch without disturbing the main trunk. When the modifications are finished you can select to either incorporate them on the main trunk, or leave them on the branch.

Creating a branch

The rtag command can be used to create a branch. The rtag command is much like tag, but it does not require that you have a working copy of the module. See section rtag--Add a tag to the RCS file. (You can also use the tag command; see section tag--Add a symbolic tag to checked out version of RCS file).

$ cvs rtag -b -r release-1-0 release-1-0-patches tc

The `-b' flag makes rtag create a branch (rather than just a symbolic revision name). `-r release-1-0' says that this branch should be rooted at the node (in the revision tree) that corresponds to the tag `release-1-0'. Note that the numeric revision number that matches `release-1-0' will probably be different from file to file. The name of the new branch is `release-1-0-patches', and the module affected is `tc'.

To fix the problem in release 1.0, you need a working copy of the branch you just created.

$ cvs checkout -r release-1-0-patches tc
$ cvs status -v driver.c backend.c
===================================================================
File: driver.c          Status: Up-to-date

    Version:            1.7     Sat Dec  5 18:25:54 1992
    RCS Version:        1.7     /usr/local/cvsroot/yoyodyne/tc/driver.c,v
    Sticky Tag:         release-1-0-patches (branch: 1.7.2)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        release-1-0-patches             (branch: 1.7.2)
        release-1-0                     (revision: 1.7)

===================================================================
File: backend.c         Status: Up-to-date

    Version:            1.4     Tue Dec  1 14:39:01 1992
    RCS Version:        1.4     /usr/local/cvsroot/yoyodyne/tc/backend.c,v
    Sticky Tag:         release-1-0-patches (branch: 1.4.2)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        release-1-0-patches             (branch: 1.4.2)
        release-1-0                     (revision: 1.4)
        release-0-4                     (revision: 1.4)

As the output from the status command shows the branch number is created by adding a digit at the tail of the revision number it is based on. (If `release-1-0' corresponds to revision 1.4, the branch's revision number will be 1.4.2. For obscure reasons CVS always gives branches even numbers, starting at 2. See section Revision numbers).

Sticky tags

The `-r release-1-0-patches' flag that was given to checkout is sticky, that is, it will apply to subsequent commands in this directory. If you commit any modifications, they are committed on the branch. You can later merge the modifications into the main trunk. See section Merging.

$ vi driver.c   # Fix the bugs
$ cvs commit -m "Fixed initialization bug" driver.c
Checking in driver.c;
/usr/local/cvsroot/yoyodyne/tc/driver.c,v  <--  driver.c
new revision: 1.7.2.1; previous revision: 1.7
done
$ cvs status -v driver.c
===================================================================
File: driver.c          Status: Up-to-date

    Version:            1.7.2.1 Sat Dec  5 19:35:03 1992
    RCS Version:        1.7.2.1 /usr/local/cvsroot/yoyodyne/tc/driver.c,v
    Sticky Tag:         release-1-0-patches (branch: 1.7.2)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        release-1-0-patches             (branch: 1.7.2)
        release-1-0                     (revision: 1.7)

The sticky tags will remain on your working files until you delete them with `cvs update -A'. See section update--Bring work tree in sync with repository.

Sticky tags are not just for branches. If you check out a certain revision (such as 1.4) it will also become sticky. Subsequent `cvs update' will not retrieve the latest revision until you reset the tag with `cvs update -A'.

See the descriptions in Appendix A for more information about sticky tags. Dates and some other options can also be sticky. Again, see Appendix A for details.

Go to the previous, next section.