Version-Flow
By: Paul Ossenbruggen
Tags: Gitflow, Developer Tools, Software Development, Git, Branching Strategy

This article describes a branching model based upon other familiar branching models but is designed for versioned software releases and ensures that code reviews are done for all areas of the code. If others have proposed exactly this, I wasn’t able to find a good article on it.

Why another Git branching model?

The main advantages are a simpler model than Git-Flow, utilization of pull-requests everywhere so all code is reviewed, and the benefits of trunk based development. While GitHub-flow is good for continuous releases it is designed more for server deployments. This is very close to Release-Flow but is slightly tailored to versioned software releases, it also works well with git-flow command line tools.

Git-flow was developed in the early days of git’s life and does not work as well with PR based systems such as GitHub. One big problem is that the release branch does not get code reviewed for each commit because the tool does not support doing a PR off of the release branch (one could argue that that would be a nice feature to add). I am not claiming this branching model is truly novel, just putting together the best aspects of other branching models that work well for versioned software.

Versioned Releases?

By versioned releases I am talking about software that is released in the more traditional model, with semantic versioning, after many features are developed and then released when that feature set is defined. That point could correspond to a sprint cycle or when enough features are ready to go. You typically see this in native iOS, MacOS, or Android environments.

Other models which are not facilitated by this approach are continuous deployment models where every feature developed are immediately deployed. If you have that then definitely look at GitHub-flow or Release-flow

Comparison to Other Git Branching Models

GitHub-flow: is designed for continuous deployment in a server environment. The feature branching model works the same as what I am proposing, but the last step where it is run through CI and deployed to production does not work for versioned software. Also, it does not scale well with the CI when every feature must be queued up. Release-Flow solves that with Release branches.

Trunk-Based: This model is nice in that it is simple, all features are branched from master, tags are made when software is released. The problem is it is too simple, typically you may want other developers to continue development on other features while a release goes out which is being managed by someone else. What is missing is the release staging area, that Git-flow has, where the release can be prepped in a controlled environment where we don’t want to let other features that are less well developed to get into the release accidentally.

Release-Flow: Is very similar to Version-Flow approach but that also is designed with larger server environments in mind. It is itself based upon Trunk-Based where there is one main branch but adds an integration(release) branch which is disposed of after each release. It uses cherry-picks to bring bug fixes into the integrations, as does Version-flow.

Git-Flow: Is a tried and true branching model that has been around for a long time. There are many features that probably are not necessary and make it more complex. One of those features are hot-fixes. As mentioned earlier the release branch is not easily, without resorting to regular git commands to do PRs. If it works for you then that is fine, this is about streamlining it a bit and fixing the code review issue with the release branch.

Version-Flow Branching Model

Version-Flow

There are many similarities to the above mentioned branching models. It keeps the release, master and develop branches defined in Git-Flow. One goal is all code is code reviewed before getting merged to release this is something git-flow release branch model does not do.

In this model, master is only for tagging releases. This makes it easy to see what releases have been made in a straightforward timeline. The master branch is completely optional but one of the goals of this was for it to work with the git-flow command line tools which is setup in the defaults to create a master. This branch is expected to have the latest version of the software that shipped at its head and should have a clean commit history in it that only shows the merge commits for each release in it for easy diffing of past versions. To keep things simple, we don’t do hot-fixes off master, they should be done on the develop branches through feature pull requests.

In Git-hub you should set your default branch to develop in the settings for your project. Also, it should be set to require PRs to the develop branch. Also, it is recommended but not necessary to install the git-flow command-line tools. On macOS that can be done through brew or other tools.

Development is done through feature pull requests off of develop branch, as other branching models specify. All commits to develop are through PRs. This branch should be treated like a trunk branch in the trunk model.

When it is determined it is time to start a release, create the release branch from develop. This means that feature development for the release is complete, only bug fixes should go in this staging area. If it is later found that a new feature needs to go in, then just cancel the branch and start a new release from develop. Generally, this means it will pickup any other completed features from development if they were completed in the time frame past when the release was started. But there may be situations where it is better to cherry-pick over a whole feature or a squashed feature rather than doing this. The risks with cherry-picking are that it is like copying the code from one branch to another and they lose parent information, but for a bug fix or small feature fix this should be minimal trouble, and since git is good at not creating conflicts for code that is identical it should not create conflicts.

If a bug fix is required it is done on a feature branch off of the develop branch, reviewed by PR, tested, and cherry picked to the release branch. Only cherry-picks are done to the release branch. Since they are only bug fixes they probably will not have many commits to bring over to release. Doing the bug fix on develop, ensures that the bug does not get lost as is advocated by the Release-Flow model.

The builds for release will be triggered from the release branch for example 2.9.1 and given to QA for validation. If more bug fixes are necessary this will repeat until it is a release candidate.

When the release is approved and shipped, then the release branch is merged to develop and merged to master, tagged, and the release branch is deleted. There should not be any or few conflicts in this process. The git-flow tools ensure merging to both branches is done, creates the tags and deletes the release branch.

Hot-fixes are not part of this model as a simplification and ensures that go through the same flow with PRs for every commit.

Examples

Regular feature development:

Assumes you have git-flow tools installed (there are also, shortcuts in oh-my-zsh if you install the plugin for git-flow tools). Start work on a feature:

git flow feature start Ticket-2991

publish the feature for a PR:

git flow feature publish Ticket-2991

go to git-hub and create pull request, get it reviewed, merge it:

git flow feature finish Ticket-2991

To be sure to get merged results, delete branch and avoid conflicts:

git reset — hard origin/develop git pull

Start release branch:

Create branch and publish it for PR:

git flow release start 2.9.1 git flow release pubish 2.9.1

If needed for bug fix, follow regular feature development flow for bug, then cherry-pick bug commit over.

git cherry-pick 239218

then when release PR is approved and release is shipped, the following will ensure the branch is deleted, the branches are merged, and the tags are pushed to git hub:

git flow release finish 2.9.1 git push — tags git reset — hard origin/master git pull Things I don’t talk about is version numbers but the git flow tools walk you through that. They remind you to bump a version number when starting a release.

Conclusion

With this branching model it simplifies the process with consistent flow of features from the develop branch to the release. It facilitates versioned software which tends to be released as a grouping of features rather than as each featured developed by having a release staging area. It ensures that all code is reviewed at two levels, one is the development phase, and again at the release phase when the group of features is ready to be shipped.