Stefan Monnier, 04/21/2000
It is pretty common to use
foobar-branch-tag and foobar-banch-tag-rootinstead of
foobar-devel-tag and foobar-main-tagthere have been proposals on the CVS list to provide an automatic way to get the "root" with something like foobar-branch-tag.0 or foobar-branch-tag.ROOT or somesuch. Of course, nothing came of these, since CVS development is close enough to moribund.
The problem Matthias mentions when merging changes from the trunk to the branch can be solved in the following way [Note: I assume that the user has put `update -dP' in his ~/.cvsrc file.]:
cd ~/ML/MainTrunk/smlnj cvs update cvs tag joe-tmp
cd ~/ML/smlnj cvs update -j joe_main_v110p27p4_2 -j joe-tmp
cvs rtag -d joe_main_v110p27p4_2 cvs tag -r joe-tmp joe_main_v110p27p4_2 cvs tag -d joe-tmp
cvs rtag -d
' and
`cvs tag
' I could just use
`cvs tag -F
', except that it would not remove the
tag on files that were removed between the two points.
The advantage of moving the root tag like this instead of creating
a new branch is that it requires fewer steps and that it doesn't pollute
RCS files nearly as much (do a `cvs log
' on a few files
in the current directory and you'll see the impressive number of tags
compared to the fairly short age of the repository).
Also it saves you from coming up with yet-another-name.
Funnily enough, this technique relies on an explicit "root tag": an automatic foobar-branch-tag.ROOT would not cut the mustard.
CVS has many quirks which lead to several "Commandments" to help you avoid them. Among those are the following two:
cvs tag <branch>-ROOT cvs tag -b <branch>
cvs update -j <branch>but
cvs update -j <branch>-ROOT -j <branch>or
cvs update -j last-merge-on-<branch> -j <branch>To figure out what is `last-merge-on-<branch>', there are two techniques:
cvs update -j <branch>-ROOT -j <branch> <...resolve conflicts and commit...> <..there's a race condition here..> cvs tag -F -r <branch> <branch>-ROOTThis way, <branch>-ROOT always contains the last-merged revision.
Matthias was caught by the `cvs update -j <branch>' problem where he thought that CVS would automatically find the right common ancestor to do the merge. This seemed reasonable since he only had a branch off of the main trunk and hadn't merged anything back yet, so finding the ancestor should have been trivial. It turned out that his branch was made off of the magic-vendor-branch (used when importing files), so he ended up merging 1.1.1.19 (for example) and 1.3 where 1.3 is a direct descendent of 1.1.1.19, but this is muddied up by the magic-branch. The common ancestor ended up being 1.1 which happens to be the very first version I entered in the repository (i.e. 110.5 of there about).
His specific problem could have been avoided had I not used `cvs import' to create the repository, but the above two rules will save you in several other cases as well.