oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Version Control on Mac OS X, Part 3
Pages: 1, 2, 3

Updating a Released Version with CVS branch

A common maintenance task is fixing bugs in released versions. If a bug in an earlier release is discovered, you are faced with a problem. How do you fix the bug when new code has been added to the trunk? One solution is to check out the tagged release and fix the bug, but how do you record the changes with CVS? Another option is to fix the bug in your current code base, but here you run the risk of releasing a new version that is unstable. To solve this problem, you use the CVS branch command.

As you saw earlier, the branch command enables you to create and manage different versions of your project. Basically, a branch is a specialized version of your program, rooted on a tagged trunk or possibly another branch. The following steps show how to fix the bug in the released version of MyPing and record the changes with CVS, using the branch command.

Step 1: Check out the Version to Update

This first step is to check out the release you will fix. In this case, the version we tagged as tag release_1_0-public-release.

% cvs co -d MyPing_release_1_0-public-release -r release_1_0-public-
release MyPing

Step 2: Create a New Branch

To create a branch, follow these steps.

  1. Create a new branch. Conceptually, think of a branch as rooted to the trunk, starting with a release tag and labeled using a branch tag.

    % cvs tag -b [name-of-branch-tag]} 

    For our project, do the following:

    % cd MyPing_release_1_0-public-release
    % cvs tag -b release_1_0-public-release-branch-bug-fixes
  2. Check out the newly tagged branch. This is the version you wish to update with your changes, which forms the basis for the new updated release.

    Note: there are different ways to do this, but this is the simplest and safest.

    % cvs co -d [dir-to-place-version] -r [release-tag] [location-of-dir-
    % cvs co -d release_1_0-public-release-bug-fixes -r
    release_1_0-public-release-branch-bug-fixes MyPing
  3. Update/modify branched code. Make changes in the branched version and commit changes. It's important to remember that committed changes go to the branch, not the trunk.

    The bug in MyPing occurs in the appendOutput method in PingController.m.

    // ---------------- Begin New Code for Article 3 ------------------
      // Log to the file, only if the file point is valid.
      if (fp != NULL) {
        fprintf(fp, "%s", [outStr cString]);
        [AppSupport setStatusMsg:output theMsg:outStr];
        [self performSelector:@selector(scrollToVisible:) withObject:nil 
      // ---------------- End New Code for Article 3 ------------------

    As you can see, the bug is caused by placing the output statements within the braces. To fix the problem, simply remove the braces.

    // ---------------- Begin New Code for Article 3 ------------------
      // Log to the file, only if the file point is valid.
      if (fp != NULL)
        fprintf(fp, "%s", [outStr cString]);
      [AppSupport setStatusMsg:output theMsg:outStr];
      [self performSelector:@selector(scrollToVisible:) withObject:nil 
      // ---------------- End New Code for Article 3 ------------------

    Make sure you perform all tests and verify your changes, making sure the release is stable before continuing.

  4. Tag the branch. Once the changes are complete, tag the branch, incrementing by 1 after each fix.
    % cvs tag [tag-name]
    % cvs tag release_1_0-public-release-bug-fixes-fix-number-1

Here is the reason for re-tagging the branch: it's possible that the changes you make to a branched version should be integrated into the trunk. For example, imagine fixing a bug in the branched version of a core library. Since the code on a branch is independent of the trunk, this does not fix the bug in the trunk, just the bug in the branch. Given that the bug still exists on the trunk, you need to fix this by updating the trunk's code with the fixed version.

Related Reading

CVS Pocket Reference
By Gregor N. Purdy

You re-tag the branch to address this situation. Imagine, after a few weeks, you need to fix a bug on the branch. If the branch is not tagged, the branch contains (at its root) the initial version before any changes, the first modified released version, and the bug fixes you just made to the previously released version. If you merge your changes back to the trunk, you get conflicts. This is because the merge command merges all changes from the branch's root to the tip, which contains your new bug fixes. The conflicts occur because you already merged some of these changes after the first release.

To solve this problem, you add a branch tag after updating a branch. This step enables you to direct CVS to merge only the new changes back to the trunk. You can also accomplish this without adding a new tag and merging by date, but this is error-prone.

In addition, you may have noticed that we added the string -fix-number-k (where k is incremented after each fix) to your tag name. This makes it very clear what is going on in the branch.

Step 4: Announce the Release

Notify users that the new release is ready.

There you have it. These descriptions of common release scenarios are by no means inclusive, nor do they show all of the things that come up in release management. Nevertheless, they do convey the main points of performing a software release. The main thing that tags and branches give you is a method of returning to (and revising) the past, and recording any changes with CVS. Using branches can be confusing at first, but hang in there and get comfortable with the concepts and commands. Once you do, you will use them all the time for your release-management tasks.

One last thing: many of the ideas presented here are based on the book Open Source Development with CVS, by Karl Fogel and Moshe Bar. I highly recommend you get a copy of this book, and best of all, it's freely available from

Other Interfaces to CVS

To conclude this article, let's take a brief look at four Mac OS X GUIs for CVS. The goal here is to give you the flavor of the tools and let you know that GUIs for CVS exist. I encourage you to try each program on your own and see if they fit into your development process and help you be more productive. You never know when you will find something that increases your productivity and fun factor.


Since the early days of the Macintosh, I have always been a big fan of BBEdit. If you have never used BBEdit, stop now, go to their web site, and download the demo. After using it a few times, I think you will be hooked.

BBEdit has always been a rock-solid editor with great features for software development and text-editing tasks. Some of the most useful stuff is its developer support, including syntax coloring, integration with the command line, internal support for Perl, Python, and shell scripting, integration with Project Builder, and most importantly for this article, integration with CVS.

To use BBEdit with your CVS repository, you can do the same trick you did with Project Builder, where you launched to from a shell with the open command. For example, change directory (cd) to the MyPing directory and type the following command (make sure BBEdit's command-line tools are installed):

% bbedit PingController.m

BBEdit's CVS menu items permit you to access its CVS commands. As you can see below, BBEdit supports many of the CVS commands you already know.

You can even configure BBEdit and Project Builder to work together. Once configured, when you open a source file in Project Builder, the file is loaded into BBEdit. When you save the file, BBEdit notifies Project Builder to update its state.

Pages: 1, 2, 3

Next Pagearrow