You should read through GettingStarted and ThingsToKnow before you read this document. It involves some complicated usage of CVS, but the instructions are kept as simple as possible. The document describes how we use CVS branching and merging to do our work safely, and how developers are expected to use it.

Branching

Every book, article, pamphlet or other document you read on CVS introduces branching and its idiot grandson tagging by going into a deep philosophical discussion that involves lots of "then this merges with that and that branches". This is usually followed by tons of ASCII art depicting some complicated branching scheme which is supposed to make things easier to understand. This wiki document will do no such thing. If you want to find out how to do advanced branching in CVS, then you should go see your doctor about some prozac first. All you need to know about branching is this
  1. Files you check into the CVS module need to go somewhere.
  2. If you don't tell the cvs command where to put the files, they go in to the "trunk" or HEAD (we'll use HEAD). Think of the HEAD as the "official" place where source code goes. Most projects just put source there and never bother with creating other places (called branches).
  3. If you tell the cvs command to put the files into a named branch, then they will go there rather than HEAD. A branch can have any name, but basically it is a way of separating out a piece of development from the HEAD. What we are doing is "branching" the timeline of the source's evolution so that we can do something weird to it without breaking the official stuff. Remember all those Star Trek episodes where they try to use time travel as a plot device, and they talk about those possible "branches" or "lines" in time? Yeah, same stupid idea and results in the same complicated confusing plots. It is useful though if used correctly (which we'll do later).

This gets confusing when the CVS manuals start talking about HEAD, and MAIN as branches, but they are not. They are just a way to refer to the "trunk" of the source tree vs. a branch such as Begin-MS2-2003-02-24. Here's how we use branches in Obversive:

1. At any one time, there is only a HEAD and milestone branch which we are dealing with. The milestone branch is labeled as Begin-MS#-DATE (like Begin-MS2-2003-02-24) to indicate the date it was begun, and what milestone it is a start of for the project.

2. Developers do the work for the each milestone on these branches. They must check-out projects using this command

cvs -d <cvsroot> co -r <current_branch_name> obversive -d <target_dir>.

For example, if we are currently on Begin-MS2-2003-02-24, then I would type

cvs -d :ext:myname@cvs.obversive.sf.net:/cvsroot/obversive co -r Begin-MS2-2003-02-24 -d obversive_MS2.

3. As you work in your obversive_MS2 directory (called a sandbox), you are checking your changes into our development branch (called Begin-MS2-2003-02-24 in example above).

4. When everyone thinks it's time to make a release, the configuration guru (currently ZedShaw) starts coordinating it. This involves everyone getting their changes in, verifying that everything is stable, and making sure all goals for the milestone are met.

5. Assuming everything is good, the configuration guru then closes off any further development into that development branch, and announces a CVS freeze. This is necessary so that the configuration guru can make the release and do some tagging magic to set things up for the next milestone's development.

6. When all is done, and everything is released, the configuration guru announces the name of the new milestone development branch (in our example, it would be something like Begin-MS3-2003-04-30 or so).

7. It is then the developers responsibility to check-out the code again into a new work directory (preferrably something like obversive_MS3) and then work commences on the next milestone.

Couldn't be any simpler. When you first do this, you will probably screw it up, but that's OK. Remember, it's not your fault as CVS is a really hard to use tool in this case. Make sure that you do a test commit of something useless (like write a test message to a comment or something...don't create a file) and make sure the other developers pick it up. If they see it in their sandbox, then you're good. Otherwise, you would just do your work like normal.

The Complicated Part: Merging

Developers will not have to do this, so you can skip this part if you are not doing the configuration guru's job. The merging portion of this document is just for future reference to document the procudure the current configuration guru uses. It is as simple as possible to fit the above CVS model.

The merging process only happens when there is a release, and releases only happen off the HEAD. The summary of what happens is that the configuration guru calls a CVS freeze, tags the HEAD with Merge-MS#-DATE, then takes the changes from the current development branch and merges them into that tag. Notice I said tag not branch in that last sentence. Merge-MS#-DATE is a tag since it is intended to just mark the place where changes from MS# were merged in to HEAD. If all goes well, then another tag is applied to HEAD with the name Release-MS#-DATE to indicate the end of the merging and the place where the release was made. Again, it's a tag not a branch. Finally, the configuration guru packages up the release and ships it out. When that's all done, a new branch (yep, you can use a branch now) is created for the developers to work on with the name Begin-MS#-DATE.

For this example, let's say we are on Begin-MS2-DATE, and we want to do a release to start working on a new branch called Begin-MS3-DATE. Here's that same information in procedural form:

1. Announce CVS freeze. Punish all evil doers who violate it.

2. Create a sandbox with the latest HEAD in it so we can tag it
cvs -d <cvsroot> co obversive -d obversive_Merge-MS2

3. Tag the obversive_Merge-MS2 directory with the Merge-MS2-DATE tag. Do a commit just to be safe. There is now a marker indicating the point in HEAD just before you tried to merge.

cvs tag Merge-MS2-DATE

cvs commit

4. Create another sandbox with the latest HEAD for merging in the Begin-MS#-DATE branch that development is on.

cvs -d <cvsroot> co obversive -d obversive_HEAD

5. Merge in the changes from the current development branch into our newly tagged obversive_HEAD directory.

cvs -q update -d -j Begin-MS2-DATE

6. Fix any conflicts (shouldn't be any really) and commit the changes so they are part of HEAD.

cvs commit

7. HEAD now has the changes from Begin-MS2-DATE. In the same directory, do a tag of the contents to add a Release-MS2-DATE tag for future reference.

cvs tag Release-MS2-DATE

8. Finally, create another sandbox for the new Begin-MS#-DATE branch for the next round of development by checking out the new HEAD and making a branch with the new name.

cvs -d <cvsroot> co obversive -d obversive_MS3

cd obversive_MS3

cvs -q tag -b Begin-MS3-DATE

9. Tell everyone the name of the new branch (Begin-MS3-DATE) so they can start developing on it. They should create a new directory to work in either abandon the old one, or keep it around for future reference.

That's all for the merging process. It's more complicated than regular development, but it is kept fairly simple and designed to eliminate the problem of merge conflicts (which are really nasty). It also lets you back up to a previous release, go to a release to add bugfixes on a new branch (a bugfix branch), or just see what the source was like at previous tags.


Last edited on Monday, April 14, 2003 12:39:28 am.


Edit PageHistory Diff Info