One of the most powerful features of CVS is the ability to maintain multiple development branches simultaneously. This complete example demonstrates how it's done.
Let's say you have a repository containing a single file mypoem.txt
that is ready to release. Let's look at the file contents:
% cat mypoem.txt
Little Miss Muffet
sat on a tuffet
eat her curds and whey.
When you officially "release" the file to your customers you create
a tag in the repository, a symbolic reminder of the state of the
repository at a certain point in time. The -b option says
we want to associate the tag with a new branch of the
repository. Maintenance will occur in the branch while new
development will continue on the trunk. Let's name our tag release-1
using the cvs tag command. The command is issued
from within your working directory, but it really affects the
repository.
% cvs tag -b release-1
Note: the working directory still contains the trunk (not the branch we just created) -- any changes committed here will go into the trunk of the repository. So now our developers can happily begin working on release 2 which will contain the "new features and enhancements" -- the next stanza of the poem.
% cat mypoem.txt
Little Miss Muffet
sat on a tuffet
eat her curds and whey.
Along came a strider
and sat up beside her.
The developers add their new work to the trunk.
% cvs update mypoem.txtNote the new work hasn't been tested yet; it has defects. It's still under development.
% cvs commit mypoem.txt
% cvs update -r release-1 mypoem.txtNotice that we are back to the Release 1 version of the file.
U mypoem.txt
% cat mypoem.txt
Little Miss Muffet
sat on a tuffet
eat her curds and whey.
Now we repair the Release 1 file only in the maintenance branch.
+---------+
Release-1 -> __! 1.2.2.1 ! <- the maintenance branch
/ +---------+
/
/
+-----+/ +-----+ +-----+
! 1.0 !---! 1.1 !----! 1.2 ! <- The main trunk
+-----+ +-----+ +-----+
% cat mypoem.txt
Little Miss Muffet
sat on a tuffet
eating her curds and whey.
% cvs update mypoem.txtAs soon as the fixes are in we can create a Release 1.1 patch that we can give the customer immediately. The patch will be made from the maintenance branch and will contain none of the new development. In the meantime new development can occur on our main development line (trunk) without any interference from bugfixes.
% cvs commit mypoem.txt
% cvs update -A mypoem.txtAnd we see that the file in our working directory is the one in the trunk.
% cat mypoem.txtWe continue development in the trunk getting the next stanza of the poem in order. It would be silly to do bugfixes two times, one time in the branch and one time in the trunk. So we ignore those little Release 1 defects and concentrate on putting in the new features.
Little Miss Muffet
sat on a tuffet
eat her curds and whey.
Along came a strider
and sat up beside her.
% cat mypoem.txt
Little Miss Muffet
sat on a tuffet
eat her curds and whey.
Along came a spider
and sat down beside her.
% cvs update mypoem.txt
% cvs commit mypoem.txt
Now the new features are finished but the trunk doesn't have the bug
fixes we made to create the patch release. At this point we want to
combine the bug fixes from the maintenance branch with the new
development. This is called merging. We use the -j
flag to merge the branched sources into the sources in our working
directory.
% cvs update -j release-1
There could quite possibly be conflicts if any of the bug fixes
overlap the new development. Watch for the message "conflicts
during merge" in the CVS output to indicate conflict.
For example, after merging the Release 1 poem our source file has
conflicts shown where the <<<<<<< symbols
appear.
% cat mypoem.txt
Little Miss Muffet
sat on a tuffet
<<<<<<< mypoem.txt
eat her curds and whey.
Along came a spider
and sat down beside her.
=======
eating her curds and whey.
>>>>>>> 1.3.2.1
Any conflicts must be manually resolved by editting the file and
running the tests again. When all is done we can commit the
changes.
% cvs update mypoem.txtHere is the view after the merge. It shows new development in parallel with bugfixes and then merging the sources back into the trunk. At this point, the patches are also in our main development line.
% cvs commit mypoem.txt
+---------+
Release-1 -> __! 1.2.2.1 !____ <- the maintenance branch
/ +---------+ \
/ \
/ \
+-----+/ +-----+ +-----+ \+-----+
! 1.0 !---! 1.1 !----! 1.2 !----! 2.0 ! <- The main trunk
+-----+ +-----+ +-----+ +-----+
Lastly we tag and branch the next release.
% cvs tag -b release-2
% cvs status mypoem.txtNotice the Sticky Tag: field shows if we are working on the branch. If we are in the trunk it will say (none).
===================================================================
File: mypoem.txt Status: Up-to-date
Working revision: 1.3.2.1 Sat Apr 10 18:33:47 2004
Repository revision: 1.3.2.1 cvsroot/mypoem.txt,v
Sticky Tag: release-1 (branch: 1.3.2)
Sticky Date: (none)
Sticky Options: (none)
% cvs checkout .
To check out the branch
% cvs checkout -r release-1 .
The -r flag will set a "sticky tag"
in the CVS/Tag file, so that most subsequent CVS commands (including commit
and update) operate on the branch instead of on the trunk,
without your having to specify the
branch name. For example, if you have used checkout -r to get
the latest copies of the maintenance files, and then changed mypoem.txt,
you can commit changes by the usual method:
% cvs update mypoem.txt
% cvs commit