Branches

Last modified: August 16, 2008 - 08:52

How you maintain the CVS branches for your projects is very important, since that allows you to properly manage changes. It also determines what snapshot releases are available. There are three kinds of branches to consider:

  • Stable branches that are compatible with a fixed version of Drupal core.
  • Development branches for adding new features that are compatible with an older version of Drupal core.
  • The HEAD branch, for active development and porting to the latest version of Drupal core.

Note that branching is restricted to the 'modules', 'themes', 'theme-engines' and 'translations' directories of the contributions repository. You can not branch your sandbox.

Also note that you must have created a project page before you can branch your module.

For more information on CVS branches see:
http://drupal.org/handbook/cvs/introduction#branches-and-tags
http://www.cvshome.org/docs/manual/cvs-1.11.6/cvs_5.html#SEC54
http://cvsbook.red-bean.com/cvsbook.html#Branches


Stable branches for a specific version of core

Once a contribution has been ported to a given version of the Drupal core API, you should create a new branch for it. This will give you a place to maintain your contribution so it remains compatible with that specific version of core. These stable branches should only be used for fixing bugs and applying security patches. This gives users of your module a stable code-base compatible with a fixed version of Drupal core to build their production sites.

These stable branches should consist of the branch names used by Drupal core, followed by the major version number of the contributed code itself. For example, DRUPAL-6--1 for the 6.x-1.x versions of the contributed code. See Branches and tags for core for details on this or the list of Available Drupal core branches.

For example, to properly branch your code once it is compatible with the 6.x core API, perform the following in your local workspace:

Modules:
cvs tag -b DRUPAL-6--1 modules/mymodule
Themes:
cvs tag -b DRUPAL-6--1 themes/mytheme

All later updates on that released version need to be done from the selected branch and committed to that branch.

Historically, the Drupal Contributions repository supported 'partial' branch names like DRUPAL-4-7 and DRUPAL-5, treating them as synonyms for DRUPAL-4-7--1 and DRUPAL-5--1 (do not use the --1 for Drupal 5 or earlier branches). Starting with the DRUPAL-6 core branch, code in the contributions repository must use fully-named branches, like DRUPAL-6--1 and DRUPAL-6--2.


Development branches for new functionality

If you want to make a new branch off of your DRUPAL-6--1 branch for adding new features, you'd do this:

cd contributions/modules/your_module
cvs update -r DRUPAL-6--1 # updates to the end of the DRUPAL-6--1 branch
cvs tag -b DRUPAL-6--2 # creates the new branch


There are a few different approaches to how you can use the HEAD branch for your contribution, depending on how closely you want to "chase" the latest changes to the next version of core under development. In general, the first approach is the recommended one, but both have advantages depending on your needs and abilities.

Use it for the "new feature" branch for the current stable core

In this approach, you would only attempt to port your contribution to a new version of core once the API had stabilized and the code freeze was well under way (for example, once the release candidates were already out). Any bug fixes you make in your current stable branch should be committed to HEAD as well. Additionally, new features or any major changes to your code should be developed directly in HEAD. You can tag official releases in HEAD, but identify them as the development series for the previous version of core.

Eventually, you'll decide it is safe to update the module to the next version of core. At this point you should make a new branch for your previously developed features, before you start porting to the latest version of core. Once that branch was created, you would convert your module in HEAD, and when you consider it stable enough for an official release, you would create a new stable branch that was compatible with the new version of core.

For example, during the entire period when the 6.0 core release was being developed, the HEAD of your module would remain compatible with the 5.x core API. Any bugs you fix on the DRUPAL-5 branch would be committed to HEAD, but you would also add new features and do other major changes there. Once you had a set of new features working well enough to release, you would add the DRUPAL-5--2-0 tag to a workspace checked out from HEAD and submit a release node pointing to this tag (which would be version 5.x-2.0). Time goes on, and you add more features, so you create the DRUPAL-5--2-1 tag for the 5.x-2.1 release and so on. At some point, you feel like the 6.x core API is stable enough to port your module to, so you add the DRUPAL-5--2 branch off the end of HEAD so you could continue to make 5.x-2.x releases if you needed to (for example, to fix a security hole in the 5.x-2.2 release). Now, you can update your module, and when it is stable, you add a DRUPAL-6--1 branch and start the whole process over again as the Drupal core 7.x API is developed in the core repository's HEAD branch. Note: beware that this example is spanning the period when the --1 was added for the initial stable branch, so don't be confused. DRUPAL-5 is valid for legacy reasons, DRUPAL-6--1 is valid because that's the correct convention going forward, whereas DRUPAL-5--1 and DRUPAL-6 are both invalid.

Keep up with the version of core currently under development

This approach assumes a more active involvement with the development of the next version of Drupal core. Whenever changes are made in the HEAD of core, you would try to update your contribution's HEAD so that it continued to work with the new API or took advantage of the latest feature. In this case, if you wanted to add new features to your contribution that were compatible with the previous version of core, you would make a branch off of your previous stable branch. Bug fixes to the stable branch would be applied to the development branch (if it exists) and HEAD. New features would be applied only to the development branch and HEAD.

Since the core API usually changes a lot during the development cycle for a new version, this approach will often require more work for contribution maintainers. Also, it's less likely that patches for bug fixes against your current stable code would apply to the HEAD version, since you've already modified the code to stay current with the latest changes to core.

Only sync changes to HEAD when you're going to start a new branch

Another viable approach to HEAD is to basically ignore it during most of your development, and only sync the changes back to HEAD when you're ready to create a new branch moving forward. In this case, you always create a branch for whatever release series you want to work on and do most of your work directly in that branch. When you're ready to create a new branch, you first copy the latest versions of the files from your most current branch back to HEAD. Then, you create a new branch from that point and carry on. This has a the nice benefit that you're always working in a branch that is named with exactly what version of the code it's for. By merging changes back into HEAD and branching from there, you prevent CVS's revision numbers from getting insanely long.

For TortoiseCVS users

fgm - January 28, 2006 - 10:22

- Open windows explorer,
- go to the root of your project
- single-left click on said root to select it
- single right click to access the context menu
- choose CVS/Branch

At this point a dialog opens, in which you can select from the existing branches, or create a new branch.

For WinCVS users

Steven - April 13, 2006 - 15:21

To branch a module to e.g. 4.7, select your files and use the menu command Modify -> Create a branch. Enter DRUPAL-4-7 as the New branch name and click Ok.

Be careful with Branches

joshk - May 13, 2006 - 21:20

Be careful with the -b flag. If you do that, you're going to create a new code branch, which means you'll have to maintain this separately from HEAD.

You may be better off waiting until your HEAD code no longer works with 4.7 (or whatever the current stable release is) before branching. That way you can keep one set of files, and just update the tag (same syntax, but without the -b flag) when you are ready to make your most recent code visable to the 4.7 tarring mechanism.

If you mistakenly branch something you can cvs -dB to clear it out.

------
Personal: Outlandish Josh

To commit to a branch:

JamieR - July 10, 2006 - 21:32

All later updates on that released version need to be done from the selected branch and committed to that branch.

This seems to be the way to commit to a branch:

~/drupal-cvs$ cvs checkout -r DRUPAL-4-7 contributions/modules/fileshare
~/drupal-cvs$ cd contributions/modules/fileshare
~/drupal-cvs/contributions/modules/fileshare$ cvs commit

When you checkout from the branch the branch tag is "sticky" and cvs remembers to commit back to that branch. I dont' know for how long it remembers that, I've been doing the checkout every time.

Then to go back to working with MAIN or HEAD:

JamieR - October 14, 2006 - 08:51

This will delete the current branch files so that you can switch to another branch or back to MAIN:

~/drupal-cvs$ cvs release -d contributions/modules/fileshare

Then this will checkout MAIN so that when you commit you will commit to MAIN or HEAD or in the downloads area is refered to as cvs...

~/drupal-cvs$ cvs checkout contributions/modules/fileshare

FYI - I found this very handy and simple to undersand:
http://developer.apple.com/internet/opensource/cvsoverview.html

"cvs update -A" is much easier

dww - October 16, 2006 - 18:04

if you have a workspace checked out from a specific branch (e.g. DRUPAL-4-7) and you want to move that workspace back to the HEAD (or trunk of the repository), all you need to do is:

cd contributions/modules/your_module
cvs update -A

forget about cvs release, that's not needed and extra complication...

sticky tags are forever...

dww - October 16, 2006 - 18:08

CVS's sticky tag remain in a workspace forever, until you manually change/clear them. The way to change them is to use cvs checkout or cvs update to ask for files from a different branch in the same workspace. For example, if you've checked out the DRUPAL-4-7 branch, here are some options:

  • Move to the DRUPAL-5 branch:
    cvs update -r DRUPAL-5 [your directory]
  • Move to the HEAD (trunk of the repository):
    cvs update -A [your directory]
  • another approach for HEAD

    aufumy - August 15, 2008 - 19:20

    Instead of keeping HEAD updated, and only creating a branch when the code is stable for the new drupal release, another way is to not deal with HEAD, and create a new branch whenever the module is in the process of being updated.

    This way it is clear what drupal version the module code belongs to, and a patch or fix does not need to be applied twice if there is an existing branch.

    Folded a modified version of this in as a 3rd strategy

    dww - August 16, 2008 - 08:55

    You raise a good point. However, I wouldn't recommend "not deal[ing] with HEAD" at all. If you keep creating branches off branches off branches, the CVS revision numbers for the files start to become insanely long (each time you branch, you add at least 2 digits).

    I'll delete these comments in a few days, now that your suggestion was incorporated -- just wanted to reply here so you see why your comment will disappear. ;)

    Thanks,
    -Derek

     
     

    Drupal is a registered trademark of Dries Buytaert.