The trendy name for the Release Branching strategy

Release Flow

Developing

Branching for development

Basic Feature Branches

For the majority of development, basic feature branches will do just fine. Simple, short-lived feature branching from and back to the mainline via pull requests.

Release Flow - Development Experience - Basic

Advanced Feature Branching

Occasionally, a team may find it necessary to facilitate concurrent development on a feature. Perhaps a number of components have been identified in the design and there are clear interface boundaries between these components. Team members wish to develop these components independently. This can be accomplished by using a base branch for a feature/user story which defined the necessary interfaces and boundary types. Branches for tasks can then be created from this base branch.

Release Flow - Development Experience - Basic

Depending on the scenario, it might be acceptable to just let the first task branch merge to the mainline, which would also introduce the necessary interfaces and boundary types. Another approach would be for the task branches to merge back to the base story branch and then have that story branch merged to the mainline. The obvious downside of the latter approach is a larger pull request to review.

Releasing

Branching for releases

A branch for a release is useful, but not always required. If a release can be cut right from the mainline, then that's exactly what should be done. More importantly, regardless of the source branch, releases should always result in a tag of the repository. The tag provides the necessary anchor point which is critical for maintenance of that release.

A release tag should use a three segment number as defined in Semantic Versioning 2.0.0:

Should a release branch be necessary, it should be named using the first two segments of the release version. An x should be used for the third segment, signifying that the branch is open for PATCH changes which result in new releases where only the third segment of the version number is incremented. An example branch name might be release/1.1.x from which you'd expect tags such as 1.1.0, 1.1.1 and 1.1.2.

The sweet spot

Ideally, develop on short-lived feature branches that originate from and terminate on the mainline. A feature branch facilitates isolation of the changes being introduced and makes peer-review super simple. Releases can just keep flowing right from the mainline.

Release Flow - Releasing Experience - Basic

Life aint always simple

Unfortunately, some business contexts don't lend themselves to continual releases from the mainline. Perhaps some manual or long-running tasks are required to support activities like approvals, testing or hardening. Simply create a release branch so that feature development can continue on the mainline.

Release Flow - Releasing Experience - Intermediate

Controlled Complexity

Other teams sometimes have to support more than one ongoing release while continuing feature development for some future release. No problem.

Release Flow - Releasing Experience - Advanced

Maintaining

Branching for maintenance

How do I... ?

You may wonder if there are some maintenance scenarios that releaseflow might not support. After all, it's a simple strategy. Perhaps there are some more complex use cases that aren't supported? We've not uncovered such a problem so far. Here are a few "How do I..." questions and answers which might just help settle your nerves.

How do I find the code running in production?

Each release has a corresponding tag. To find the exact code running in production one simply needs to determine the version of the application deployed. Once known, the corresponding tag can be used to navigate to the code at the exact commit deployed in production.

How do I fix a defect?

Similarly to adding a new feature, the starting point must be determining the target of the defect. Next, a new branch should be created from the target with a name referencing the defect such as fix/DE1234. The defect remedial action should take place on this branch and result in a merge request to have the fix applied to the target branch. Finally, the merge request reviewers should also ensure this fix is applied (usually cherry-picked) to other branches where necessary, e.g. master and/or ongoing release branches. How do I ensure a defect fix is applied to future/past versions? As above, the merge request reviewers should also ensure this fix is applied (usually cherry-picked) to other branches where necessary, e.g. master and/or ongoing release branches.

How do I add a new feature?

Firstly, one must determine the target of a new feature. This will usually be master where the latest development is in motion. Of course, if the feature is to target a specific release, then the corresponding release branch should be sought out. Secondly, a new branch should be created from the target. The branch should be given a useful name, usually a user story reference with a feature prefix, i.e. feature/US1234. Thirdly, feature work should happen on this branch and finally a merge request should be raised to have the feature pulled into the target branch.

Definition

Making it clear

The "Release Branching Strategy" is an industry-standard approach which advocates that the only type of long-lived branches - apart from the mainline - are release branches. This strategy is documented and recommended in the Continuous Integration book [CD].

The mainline branch (e.g. master) is used for cutting edge development as recommended in the Continuous Integration [CD] text which advocates the approach of "Develop on mainline".

Of course, it is normal, and encouraged, to use short-lived branches for developing features and fixing defects.

Branch Roles

There are a number of different branch types in the releaseflow strategy. Each has their role to play.

Mainline

The main branch, i.e. master, is where the latest development occurs and where continuous integration is always applied at the build server.

Features

Short-lived branches, lasting days rather than weeks, where new features can be developed without affecting the the mainline. These branches should be named appropriately for the given feature. Imagine working on user story with identifier US-134, then the appropriate name for your branch would be feature/US-134.

To aid team working for a new feature, it may prove useful to create a branch for a user story and then further task branches from that branch for development of distinct components. However, only make this as complex as is needed. If individual tasks can be performed on a single feature branch from the mainline, then prefer this simpler option.

Releases

As aforementioned, the only type of long-lived branch is for releases. Features and defects are short-lived branches from their target branch, either master or a release branch.

Typically, a release will be performed from its own release branch and named after the major and minor version it manages followed by an x for the patch version, i.e. 1.1.x. The x for patch indicates this segment of the version will be changing on the branch. It is safe to delete a release branch once release activities are complete since it can be easily re-created from a release tag.

In circumstances where a release doesn't need to be isolated onto its own branch, it is perfectly fine to release from master. Of course, this should be exercised with caution to ensure only the desired commits are rolled into the release. The flexibility to allow releases from master is beneficial since there is no need to maintain a separate release branch unless absolutely needed. It's important to note that a release maintenance branch can be easily created at any time from a release tag.

When creating a release branch from a tag, it is important that the project version is set to the next version SNAPSHOT to target the correct next release, i.e. 1.1.1 -> 1.1.2-SNAPSHOT.

Fixes

When a fix is required to an existing branch simply locate the appropriate release branch. If no branch for the release exists, simply create one from the respective tag. Once you have the release branch - the starting point for the fix - now create your fix branch. Imagine an issue named BUG-666 was discovered in the 1.1.0 release. You'd jump onto the release/1.1.x branch, create a fix branch named fix/BUG-166 and make the necessary changes.

Once the fix is ready, you'd raise a pull request to have your changes merged into the target release branch where the actual release can be performed.

Tags

Tags are always created for a release. When a final release is cut via an automated build task, a corresponding tag in the respective repository should be created, i.e. web-app-1.1.0.

References

[CD] Humble, J and Farley, D (2011). Continuous Delivery. Crawfordsville, Indiana, USA: Addison Wesley. p381-416.

About

What is this all about?

This site describes and promotes the "Release Branching Strategy". It seems that some facets of the software industry have lost the simplicity and effectiveness of this documented and proven branching strategy amongst the noise and attention around other strategies such as Gitflow.

The aim of the authors of this site is to resurrect the "Release Branching Strategy", known in some quarters as "Trunk Based Development" and "Develop on mainline", with a trendy name; "releaseflow". Moreover, it is hoped that this site becomes the defacto reference for documenting the branching strategy employed by teams all over the world. Just as semver.org has settled the version scheming problem, releaseflow.org aims to settle the branching strategy problem. Hopefully you'll never need to document your software development team's branching strategy again; just link to this site. You're welcome.

Why the name releaseflow? Well, the "flow" suffix is non-negotiable. Every recent branching strategy has a name containing the word "flow". As for the prefix, that's a nod towards the name given to this branching strategy in the 2011 book Continuous Integration [CD]. Coincidentally, really important meaning is conveyed in the name... the flow of releases. Every software project team wants to have a continuous flow of successful releases to their live environment(s). Employing the releaseflow branching strategy is one way to make that happen.

So you'll observe that releaseflow is nothing new and that there are certainly many software projects out there using this strategy already. Those that do so have laid the right foundation for success right through the whole development lifecycle; from initial development, through testing and into maintenance.

Appendix

The "master is production" fallacy

Two schools of thought

It is important to discuss the two main schools of thought around branching strategies; "unstable" vs "stable" trunk. If you've not been in the industry since the early 2000s, you can be forgiven for staring at your screen blankly. There's a few terms to unpack here.

The word "trunk" comes from older source control systems such as CVS and Subversion, but simply means the mainline, i.e. master in Git. As for "unstable" and "stable", this refers to the state of code. A codebase would be deemed stable if it represented the latest stable release. It follows therefore, that unstable means the latest cutting-edge changes which may not be compiling, passing tests and/or deployable.

Developing on the trunk (mainline) is deemed unstable since the branch contains the latest, cutting-edge changes and new features which are unproven and could break the build at any moment.

The idea of a stable trunk is broken

From the desire for a stable trunk, some individuals employ strategies where development is made on a separate branch and changes are only merged to the mainline when proven stable - as part of a release.

The idea of relating an environment to a branch in source-control system is flawed. The "stable" trunk philosophy does just that - trying to equate the production environment to the mainline branch. Usually, the motivation is to maintain a branch within the version control system where they can locate the code running in production. A branch is simply not needed - nor intended - to support such a use case. A tag should instead be used to mark each release. Want to find the code running in production? Simply checkout the corresponding tag! Imagine a scenario where you have multiple production environments, each potentially needing a different version? Mapping a mainline branch to a production environment is not going to be of any use.

The idea of having a mainline which matches the code deployed in production is a fallacy. The approach is flawed. Any branching strategy which stems from this school of thought should be discounted.

Why an unstable trunk fixes stuff

But isn't that contradictory?

Sure, maybe an unstable trunk sounds scary. Let's discuss that a little. Software teams should always aim to keep their mainline compiling, passing tests and deployable. If that's not the norm, then something isn't right. Any time a build failure is encountered on the mainline, engineers should jump right onto the failure and fix immediately. The "unstable" trunk approach doesn't mean engineers recklessly commit breaking changes to the mainline. However, the approach recognises that since changes are being made, stuff can go wrong sometimes.

A healthy engineering team should practice continuous integration, using a build server to automatically compile and test changes. Features should be developed on feature branches, sourced from the mainline and destined for the mainline. Pull requests should be used so peer reviews and automated builds can verify that the correct changes are being made before being accepted. Good practices minimise failures but of course don't guarantee the mainline is always completely stable.

An unstable trunk approach encourages early integration which is always better. The releaseflow strategy stems from this school of thought, along with guidance around the use of branches of features, releases and maintenance.