Semantic versioning with Drupal and Git Flow
An organized git branching model is essential for managing complexity on long-running Drupal projects. Without it, chaos ensues.
In this post, I’ll outline an approach for how to use the popular git flow methodology along with semantic versioning to organize your Drupal project. While this post is targeted towards Drupal 7, the same technique can easily be used with Drupal 8 or 6.
On small / medium Drupal projects, I’ve found that a simple GitHub Flow suffices. What is GitHub Flow? In a nutshell: whatever is merged into
master is deployable; features or bug fixes should branch off
master, and when they are ready, merged into
master and deployed. Simple. And as the author of GithHub Flow states:
Git itself is fairly complex to understand, making the workflow that you use with it more complex than necessary is simply adding more mental overhead to everybody’s day. I would always advocate using the simplest possible system that will work for your team and doing so until it doesn’t work anymore and then adding complexity only as absolutely needed.
If GitHub Flow sounds like it will suit your needs, then you don’t need to finish reading the rest of this. But for larger projects with multiple developers and a longer timeline for development, read on.
A great overview of
git-flow is outlined in this document.
The summary is:
- Branch off of
developfor feature development. When the feature is ready for client review and contains non-breaking changes, merge into
- When it’s time to release code to production, branch off of
developand create a
release/*branch. Increment versions.
- When the release is ready, merge into
masterand tag a release. Checkout the tagged release in production. Merge the release back into
- If an urgent issue or bug needs to be addressed, a hotfix branch can be created off of
master, but hotfix branches should not be used to push features more rapidly, only to deal with bugs or security issues.
Typically, we’d then have tagged releases from master deployed to production while
feature/* branches would be deployed to dev/staging environments for peer review.
You’ll note that in step #2 above, git flow requires us to increment versions for a new release.
Well, how should we decide what version numbers to use?
One of the nice improvements in Drupal 8 is the adoption of semantic versioning for Drupal core. Semantic versioning is the idea that you can understand the significance of a project update by looking at the version number. From semver.org:
Given a version number MAJOR.MINOR.PATCH, increment the:
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards-compatible manner, and
- PATCH version when you make backwards-compatible bug fixes.
How can we use this in our Drupal project? Using the following notation:
7.x-MAJOR.MINOR-rcPATCH. So, if you have a custom module like
myproject_deploy, its version number might look like
7.x-1.0-rc0. Let’s add some bug fixes:
7.x-1.0-rc1. Ok, how about new functionality in a backwards-compatible manner?
7.x-1.1-rc0. And if we make incompatible API changes?
7.x-2.0-rc0. Simple enough.
When I’ve used this workflow, I use the policy of updating every custom module, theme and install profile’s version number when creating a new release. In addition to making it clear which version of a site’s code you are using, this also means we can standardize
hook_update_N() implementations across all custom modules.
Now, we don’t want to increment every custom package version by hand, so let’s use a Drush script to automate the process. Now, whenever
git-flow prompts you to bump versions, you can run
drush @myproject.local php-script /path/to/bump-versions.php.
Questions or comments? Let me know on twitter.