CVS Branch and Merge Example
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
Parallel development
After a few days of new development the customer reports a defect in Release 1. The word "eat" is supposed to be "eating." They want a patch in a hurry. It's not a good idea to make the fixes in the trunk because it has unstable new development in it. The fixes can't get released until the new development stabilizes. The customer would have to wait until the next major release before they can get the fixes. They can't wait that long. So we have to make the fixes in the maintenance branch.To begin work on the maintenance branch, we need to get the source from the branch by referring to the tag.
% 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.
The diagram shows the situation with new versions of development going in the main trunk and bug fixes going in the maintenance branch. (Specific reversion numbers are arbitrary.)
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
When we are done with bug fixing we can return to working on Release 2. We update our working directory using the -A flag to revert our working directory to the files on the trunk.
% 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
Merging maintenance changes into the trunk
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
Finding out where you are
It's easy to forget if our working directory has source from the trunk or a branch. Use cvs status frequently to check where you are.% 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)
Summary: Checking out sources
To checkout the trunk:% 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
Note: It's recommended to follow the general strategy shown here of doing bugfixes on the fix branch and merging them to the main branch. Doing it the other way around can easily lead to the wrong changes being merged onto the fix branch (e.g. code changes related to new features that aren't implemented on the fix branch).
Here is the official CVS documentation on Branching and Merging .
Comments? Email the < language="javascript" type="text/javascript"> var name = "jdalbey@"; document.write (" author "); author .
This document was modified from the original at http://www.phenix.bnl.gov/~pope/cvs-branch.html