Problems tagging and checking in files into cvs (Sticky tags)

cvssvn

I am having some trouble with checkout out files using a release tag and hope someone here can help.

Basically my repository is structured like this:

module1
 - src
 - jsp
 - conf

module2
 - src
 - jsp
 - conf

A release can include changes in either module1 or module2 or both. Several developers could be working on any files in any of the modules.

To work on a new release, we check out the latest release (e.g., LIVE-REL-2.4) using the following command:

CVS checkout –r “LIVE-REL-2.4” moduleName

Note that we don't check out from trunc. The reason for this is that if you check out from trunc you include files that other developers have checked in, but you don't want to include in the next release.

After we've checked out the latest release, we make the changes and check back in the new files. For the delivery, we label all the new files we've checked in with a bug specific tag.

cvs tag BUG434 <file1> 
cvs tag BUG435 <file2>

We then apply a new label to every file that is on the current release.

CVS tag – r “LIVE-REL-2.4” “LIVE-REL-2.5”

We then add the new release tag for the new files we've checked in:

cvs tag –r “BUG434” “LIVE-REL-2.5”
cvs tag –r “BIG435” “LIVE-REL-2.5”

The above ensures that the new release will include all the files from the "latest delivered release" plus bug fixes that we want to include in the release. To check out the new release, we do this:

cvs checkout –r “LIVE-REL-2.5” moduleName

The checkout from the above is build tested and delivered. There is though a bit of confusion as to whether this process works. We've suddenly had people complain that they can't check in any new files if they check out by tag. The error that is generated is shown below:

sticky tag LIVE-REL-2.5' for file DatabaseFacade.java' is not a branch

I have been doing some reading on this error, but I haven't been able to find a solution to it. From what I gather from googling around, the solutions available are as follows:

run "cvs update -A" on these files to revert the working copy to the head.

This wouldn't work for me because I don't want to release the changes that are on the "head". The revision that I want to release is an updated version from the previous release. The one on the 'HEAD' could be one that someone has updated and is not to be release for the next three release.

  • The tag needs to be made into a branch.

I wish I could do this, but I can't seem to be able to convince any of my bosses that we should support branching. We don't support it because it makes things a lot more complicated than they need to be.

  • Prevent people from checking in files that are not ready to be delivered in the next release.

This might work as I would then be able to check out from 'HEAD' every time there is a new release.

Now my questions are as follows:

  • Is there some way I can checkout using the above procedure without coming across the "sticky tag is not a branch" error?
  • Is there a better way I can achieve the same steps above without having to use branching?
  • This sounds like its one of the most common situations in a development environment. How do other people do it without using branching?
  • And finally, if you have any knowledge of subversion, do you know if it works the same way, and I will have the same problems if I change to subversion?

Best Answer

The natural solution to your problem is branching. However if you have this scenario infrequently and are determined to avoid branches, you can put all your versions on the HEAD and set the tags accordingly.

Lets say you have the following version of DatabaseFacade.java:

1.1: original version, which has the bug
1.2: version with new feature, which you do not want to release yet

You checked out 1.1 and made your bug fix, but - alas - you can't commit it because you are on a sticky tag. To solve it, do the following (I didn't test the code, but it should illustrate the idea):

# backup file with fixes
mv DatabaseFacade.java DatabaseFacade.java-fixed

# revert to HEAD: remove the sticky-ness
cvs update -A DatabaseFacade.java

# get revision 1.1 (non sticky)
cvs update -p -r1.1 DatabaseFacade.java > DatabaseFacade.java

# commit it
cvs ci -m "reverted to revision 1.1." DatabaseFacade.java

# commit your file with fixes
mv DatabaseFacade.java-fixed DatabaseFacade.java
cvs ci -m "fixed BUG434" DatabaseFacade.java

# restore the latest development version to HEAD
cvs update -p -r1.2 DatabaseFacade.java > DatabaseFacade.java
cvs ci -m "reverted to revision 1.2." DatabaseFacade.java

# also fix the bug in the latest development version
cvs ci -m "fixed BUG434" DatabaseFacade.java

So now DatabaseFacade.java will have the following versions:

1.1: original version, which has the bug
1.2: version with new feature, which you do not want to release yet
1.3: same as 1.1
1.4: your bugfix to 1.1
1.5: same as 1.2
1.6: version with new feature and bugfix

Now you can tag revision 1.4 for the new release:

cvs tag -r 1.4 LIVE-REL-2.5 DatabaseFacade.java

When you take this approach, you should make sure that none of your fellow developers runs a cvs update while you are "playing with the history", i.e. while either 1.3 or 1.4 is the latest on the HEAD.


There is no benefit in switching to Subversion. It will not help you with these kind of problems. If you are seriously considering a different version management system, you should take a look at Mercurial or any other Distributed Versionmanagement System. In Mercurial, merging is painless and easy, and so branching is commonplace and harmless.


By the way: Since you are tagging your new files with bug-identifier-tags (e.g. "BUG434"), you might also want to tag any existing file related to that bugfix with the same tag.

Related Topic