A good way to do branching in CVS is to make a branch at every release and continue the main development on the trunk. Changes on the release branch that also need to be applied to the trunk can be merged back into the trunk from the branch. Having the branch will allow you to have an active working copy of the release version and continue making corrections to it without worrying about messing up the active development version and without applying every change you made in two places manually.
For an example of how to create a branch based on a release version we’ll use a revision tagged release_0630 for the head of the branch.
##$ ls
website/
##$ cvs co -d website0630 -r release_0630 website
U a whole bunch
U of stuff
##$ ls
website/ website0630/
##$ cd website0630
##$ cvs tag -b Release_0630-branch
T a whole bunch
T of stuff
##$
Branch tags are easy to confuse with other tags, so it may be a good idea to include the word branch in the tagname of a branch.
Now to actually check out that working copy as a working copy on the branch:
##$ cd ..
##$ mv website0630 website0630.bak
##$ cvs co -d website0630 -r Release_0630-branch website
(You can also change the working copy to a copy of that branch with an update command [ cvs up -r Release_0630-branch ] but be careful not to do this if you have made changes to any of the files in the working copy as it could create problems or unexpected changes to your data)
Like always, if you want to revert the working copy to the latest version on the trunk you need to clear the sticky tags:
##$ cvs up -A -d
(the -d option to up builds directories like co does)
first lets get back to the latest version on the trunk:
##$ cd ../website
##$ cvs up
Now we’ll check for differences between the trunk and the branch
##$ cvs -q diff -c -r Release_0630-branch
(the -c option to diff is for a context diff, -u is also nice)
Now we’ll pretend that we found some differences in the branch that need to be checked into the trunk
##$ cvs up -d -j Release_0630-branch
the -j option means join
Sometimes a branch will continue to be actively developed even after the trunk has undergone a merge from it. For example, this can happen if a second bug in the previous public release is discovered and has to be fixed on the branch.
If you try to merge those changes with that same command you’ll get conflicts.
What we’ll want to do to make it easiest to avoid this is to tag the branch whenever we merge changes. This way we can use the tag from the last merge as the starting point for the join.
Let’s take a look at a scenario where we’ve done this properly:
##$ pwd
website/ website0630/
##$ cd website
##$ cvs up
##$ cvs up -d -j Release_0630-branch
##$ cd ../website0630
##$ cvs up
##$ cvs tag Merge_Release0630_0708
After merging we tagged the branch, so now on July 10th when we want to merge again we can do it like this:
##$ cd ../website
##$ cvs up
##$ cvs up -d -j Merge_Release0630_0708 -j Release_0630-branch
##$ cd ../website0630
##$ cvs tag Merge_Release0630_0710
Those two -j options told it to start at the revision marked and proceed to the latest revision in the branch when determining what to merge with the trunk.
I included the branch name in the tag for merging because tag names must be unique per file, even across multiple branches. If we merged two seperate branches into the trunk on the same day it would be really easy to have problems with duplicate tag names. Adding the branch name solves that particular problem.
rtag
It is not really necessary to check out a working copy at the branch point in order to create the branch. We could have used rtags since we now the tag name of the release point:
##$ cvs rtag -b -r release_0630 Release_0630-branch website
To get a list of tags in the repository you can use cvs log. Here’s an example:
##$ cvs log index.html
Working file: index.html
head: 1.4
branch:
locks: strict
access list:
symbolic names:
Release_0630: 1.4
start: 1.1.1.1
akatombo: 1.1.1
keyword substitution: kv
total revisions: 5; selected revisions: 5
description:
----------------------------
revision 1.4
date: 2005/06/16 14:01:03; author: bob; state: Exp; lines: +150 -150
giant Japanese checkin
...
As you can see above, the symbolic names section contains a list of the tags on that file, and which revision number they are tied to