Last updated May 22, 2015.

Feature branches

In a distributed version control system workflow, like Git, it's common to spin off separate branches for features, for bug fixes, or heck, just because you feel like it. On's Git server, there are no branch/tag naming restrictions at the version control system level. You are free to name your branches whatever you like for your day-to-day work.

awesome-new-feature, experimental-redesign, performance-bugfix are all acceptable branch names.

Git's default master branch should not be used and no downloadable releases can be tied to that branch. Master branch cleanup information here. Use 6.x-1.x, 7.x-1.x or 8.x-1.x as your main development branch (see below).

Quick Aside for new Module Developers

If you are new to Git and/or module contribution, please see Creating a branch or tag in Git. If you are looking to publish your release, please view "Creating a project release" for more information.

Release branches

While there are no naming restrictions for branch and tag names in Git itself, when you want to make your changes available for download by the community on, branch and tag names need to follow a convention.

This naming convention is important for Drupal's community infrastructure, such as Update Status and the testing bot. Note that release tags must be made on the properly named release branch. Any tags/branches you intend to translate into actual downloadable releases on (as tarballs and zip files) need to follow this convention:

Branch name Branch Description Downloadable release
7.x 7.x-dev release (core) drupal-7.x-dev.tar.gz,
7.x-1.x 7.x-1.x-dev release (contrib) myproject-7.x-1.x-dev.tar.gz,
7.x-2.x 7.x-2.x-dev release (contrib) myproject-7.x-2.x-dev.tar.gz,

Packages for development releases are only created twice a day, so there may be as much as a 12 hour delay.

Tag name Tag Description Downloadable release
7.0 7.0 release (core) drupal-7.0.tar.gz,
8.0-beta1 8.0-beta1 release (core) drupal-8.0-beta1.tar.gz,
7.x-2.3 7.x-2.3 release (contrib) myproject-7.x-2.3.tar.gz,
8.x-2.0-alpha6 8.x-2.0-alpha6 release (contrib) myproject-8.x-2.0-alpha6.tar.gz,

There is a five minute delay before the creation of release packages.

Important note about release tags: Only the following labels, lowercase, can be used in release tags:

  • unstable
  • alpha
  • beta
  • rc

Read more about the distinctions between Alpha, Beta and RC here.

All release tags must end with a number. The numbers are just to distinguish releases of the same class. The first is numbered "1" (as in "alpha1"), the next "2", and so on.

7.x-1.0-rc1 will appear as a valid tag, but the following will NOT:

  • 7.x-1.0-release1 (wrong word)
  • 7.x-1.0-rc (doesn't end in a digit)
  • 7.x-1.0-UNSTABLE1 (uppercase)

Release tags usage

unstable: The project is not in a stable state. There are probably numerous unfixed bugs, including security issues. The API may change without notice. The database schema may change without hook_update_N beeing implemented. Usage and API may not be documented. Installing a new unstable release entails uninstalling the project, thereby losing all data. Only for those who want a early preview of the project. Not yet suitable for shared development.

alpha: Most reported errors are resolved, but there may still be serious outstanding known issues, including security issues. Project is not thoroughly tested, so there may also be many unknown bugs. There is a README.txt/ that documents the project and its API (if any). The API and DB schema may be unstable, but all changes to these are reported in the release notes, and hook_update_N is implemented to preserve data through schema changes, but no other upgrade/update path. Not suitable for production sites. Target audience is developers who wants to participate in testing, debugging and development of the project.

beta: All critical data loss and security bugs are resolved. If the module offers an API, it should be considered frozen, so that those using the API can start upgrading their projects. If it is an upgrade or update of a project, an upgrade/update path should be offered, and it should be possible for existing users to upgrade/update to the new version without loss of data. All documentation should be up to date. Target audience is developers who wants to participate in testing, debugging and development of the project, and developers of other projects that interfaces the project. Not generally suitable for production sites, but may be used on some production sites if the site administrator knows the project well, and knows how to handle any outstanding issues.

rc: A release candidate should only be created when the all critical bug type issues are reported fixed in the project's issue queue. This tag should only be used when the developer believes that the project is ready for use on a production site. There is no official best practice for how long a project should be a release candidate before creating a official .0 release, but it is suggested that it should be out for at least a month with status set to "needs review". If something (e.g. a new critical bug is reported) makes it necessary to create a new release during this period, a new release candidate should be created and this should remain for at least a month with status set to "needs review".

Git naming conventions compared with CVS

On the old CVS servers, you were restricted to branch names meeting a specific pattern (DRUPAL-6--2, DRUPAL-7--1, and so on). If the branch name didn't match the pattern, it was rejected. This was nice for enforcing consistency in our diverse contributor community, especially considering the limited branch and merge capabilities of CVS.

Here's how old CVS branch and tag names map to Git branch and tag names:

Branch Description CVS branch name Git branch name
7.x-dev release (core) DRUPAL-7 7.x
7.x-1.x-dev release (contrib) DRUPAL-7--1 7.x-1.x
7.x-2.x-dev release (contrib) DRUPAL-7--2 7.x-2.x
the default branch HEAD master*

* Note: Git's default master branch can be used, but no downloadable releases can be tied to that branch.

Tag Description CVS tag name Git tag name
7.0 release (core) DRUPAL-7-0 7.0
7.0-beta1 release (core) DRUPAL-7-0-BETA1 7.0-beta1
6.x-2.3 release (contrib) DRUPAL-6--2-3 6.x-2.3
6.x-2.0-alpha6 release (contrib) DRUPAL-6--2-0-ALPHA6 6.x-2.0-alpha6

So in summary, compared to CVS, Git will give you the freedom to branch early and branch often while in development, and use much less obtuse names for your tags/branches when you're ready to release. Yeehaw!

@todo: Delete this section of the page by July, 2011, as no one will care about CVS by then Delete this section when no one remembers anything about CVS. These messages serve as a reminder of CVS's existence thereby negating their purpose.


fmjrey’s picture

Please don't remove comparison with CVS version.
Drupal developers may not use CVS anymore, but there may still be websites that use CVS versions out there.
CVS comparison information should still be available for maintainers when transitioning these sites.
In any case I don't see this section becoming obsolete as soon as july 2011!

Karlheinz’s picture

I agree. What's the harm of leaving this up?


daften’s picture

This might not be the place to put it, but I don't know which page to pinpoint.
Could instructions be put up for contrib developers, so they have the same strategy used as in core. E.g. 8.x is now HEAD, no master branch.
By default git creates a master branch for local repos and no branch for bare repos, which means that you need to delete your local master branch or rename it.
Also instructions on how you can change the remote HEAD pointer would be handy.

cwithout’s picture

I believe these are the instructions for that. Moving from a master to a major version branch

jp.stacey’s picture

If git branches are called e.g. A.x-B.x, then the sudden appearance of -dev in the "branch description" and the zipfile name can be confusing: I've just had to iron this out in the office.

Going forwards, it'd be good if we could drop the whole -dev thing altogether. Or add it to the git branch naming convention too, if we really want it. Right now it makes it look like there are two branches for each actual single A.x-B.x branch.

(I appreciate these naming conventions have historical weight too, and we need to clarify especially for people coming from CVS, when the branch name was nothing like the branch description; but if anything the close similarity in git is more confusing!)

J-P Stacey, software gardener, Magnetic Phield

PeterX-dupe’s picture

Is there a code that prevents the update?

mccrodp’s picture

This doesn't mention how to deal with multiple or incremental dev tags.

What is the best practice for dev tags?

  1. delete local dev tag git tag -d 7.x-1.x-dev
  2. delete remote tag: git push --delete origin 7.x-1.x-dev
  3. tag local repo git tag 7.x-1.x-dev
  4. push tags to remote git push --tags

What are dev tags of this form 7.x-2.5+3-dev?

Should above steps instead be?

  1. tag local repo with new dev tag git tag 7.x-1.x+2-dev
  2. push tags to remote git push --tags

I haven't seen this documentation anywhere.

EDIT: Or is it that you do not tag dev releases at all and the dev release is always the HEAD of the default branch...

Mario Steinitz’s picture

Pretty sure you found out yourself already. For other visitors that stumble across this question:

You don't have to tag dev releases. In your example, the current branch 7.x-1.x is the dev branch.

When you enable your project to show snapshot releases, Drupals automatic packaging system will take care of versioning your dev packages.

Once you created a release tag/release on a commit of the dev branch, let's say 7.x-1.0, further commits to the dev branch will automatically be packed as version 7.x-1.0+[y]-dev (with [y] an automatically increased number).

awasson’s picture

@Mario Steinitz: Can you elaborate on this?

For instance if I backport a module from Drupal7 to Drupal 6 and then once I'm ready to release it, I create and push a tag "6.x-1.0", then I enable release and all is well. Anyone can come along and grab my 6.x-1.0 version of the module and install it.

Then at some point in the future I discover an bug in my code and make a change to that branch of the project and commit it; ie:

  • git add ./*
  • git commit -m "I just fixed something"
  • git push origin 6.x-1.x

Do I need to do anything further to push my changes so that they update my release?

Mario Steinitz’s picture

My above comment wasn't on automatic release creation for stable releases, but automatic versioning for published dev releases which happens automatically when pushing.

When you'd like your bugfix to be published within the recommended (stable) version of your module, you still have to create a new tag on your commit, and push it to the Drupal git repo:

    git add ./*
    git commit -m "I just fixed something"

    git tag 6.x-1.1

    git push origin 6.x-1.x

Then go to your releases section of the module's page and click "Add new release", just beyond it. Choose your tagged version, add a description and publish.

Hope this is the answer you've been looking for.


awasson’s picture

Thank you Mario Steinitz,

That is a perfectly clear explanation. Thanks for taking the time and also thanks for taking the time with the detailed explanation below.


Mario Steinitz’s picture

Let me explain more specifically:

You have created a stable release 6.x-1.0. In the "Administer releases" of your module page, you enable "Show snapshot release". This results in development releases being shown for download at your modules overview page.

Now you fix a minor issue, or are adding a minor feature, that isn't worth a new stable release. You push it to your development branch 6.x-1.x:

git add ./*
git commit -m "I just fixed something small"
git push origin 6.x-1.x

The development release seen will automatically change its version to 6.x-1.0+1-dev, as the development branch is one commit ahead the released stable version.

When you add more minor features and push them, this development version will automatically be increased by Drupals packaging system:

git add ./*
git commit -m "I added a minor feature"
git push origin 6.x-1.x

Will result in 6.x-1.0+2-dev, and so on.

Once you reached a version that is worth a new stable release, you tag your last commit with the new release number:

git add ./*
git commit -m "This is the awesome stable version"
git tag 6.x-1.1
git push origin 6.x-1.x

Now you add the new release to your modules page and it will be available for download as new recommended version within your module downloads.

The same applies to older, and 7.x or 8.x branches.