A test repo for trialing branching strategies and confirming our adoption and standards. We aim to use GitFlow as our primary strategy.
Guidance is largely stolen from the following articles:
- nvie.com/posts/a-successful-git-branching-model/
- datasift.github.io/gitflow/index.html
- theserverside.com/blog/Gitflow-release-branch-process-start-finish
Gitflow is a branching model for Git, coined by Vincent Driessen in 2010. It has been largely adopted by many teams as it is very well suited to support collaboration and scaling the development team whilst supporting changes and potential hot fixes.
Vincent Driessen has exercised some caution and he has since suggested a simpler GitHub Flow
for scenarios whereby software is continuously delivered and does not need to support multiple or explicit versioning. nvie.com/posts/a-successful-git-branching-model/
Although our applications are largely Web based, continuously delivered and only one production version, we still required explicit versioning. There are also other benefits and will continue and formalise our strategy with Gitflow. This repository's goal is to explain this but also provide a test bed for branching, versioning and packaging.
Each repo should infinitely hold two main branches:
main
(could be known asmain
for more inclusive language)develop
(default, compare)
For our purposes we have retained the name master
in some existing projects and moved to main
for newly created repositories.
We consider origin/main
to be the main branch where the source code of HEAD always reflects a production-ready state. This is the build that get's packaged and versioned as the release
- The
main
branch tracks released code only. - The only commits to
main
are merges from release branches and hotfix branches.
We consider origin/develop
to be the main branch where the source code of HEAD always reflects a state with the latest delivered development changes for the next release. Some would call this the integration branch
.
This is where any automatic nightly builds are built from - which we don't do today but could/should -
The different types of branches we may use are:
Feature branches:
feature/*
bugfix/*
(not a hotfix branch and still acts like a feature branch and the same flow as features)
Release branches:
release/*
(the shortest lived of all Gitflow branches)
Hotfix branches:
hotfix/*
We consider origin/develop
to be the main branch where the source code of HEAD always reflects a state with the latest delivered development changes for the next release. Some would call this the integration branch
.
This is where any automatic nightly builds are built from - which we don't do today but could/should
May branch off from:
develop
Must merge back into:
develop
Feature branches are branched off of the develop branch, and finished features and fixes are merged back into the develop branch when they’re ready for release
When it is time to make a release, a release branch is created off of develop:
Release branches isn't the branch to trigger a deployment but rather a branch for formalising and merging in changes ready for a deployment.
When the release is finished, the release branch is merged into main
as well as develop
, to make sure that any changes made in the release branch aren't accidentally lost by new development.
The code in the release branch is deployed onto a suitable test environment, tested, and any problems are fixed directly in the release branch. This deploy -> test -> fix -> redeploy -> retest cycle
continues until you’re happy that the release is good enough to release to customers.
May branch off from: develop
Must merge back into:develop
and main
Branch naming convention:
rc/*
Hotfix branches are created directly off the main
branch
Gitflow is a strategy and doesn't require any install as such however git does provide some helpers. Using the helpers enforces sticking with the strategy and therefore recommended.
Below is the git flow helper commands vs what commands get ran by git. Useful to understand what each command executes. You could run the individual git commands manually should you wish.
Configures the develop and main branches
gitflow | git |
---|---|
git flow init |
git init |
git commit --allow-empty -m "Initial commit" |
|
git checkout -b develop main |
Creates feature branch ensuring it's from develop branch
gitflow | git |
---|---|
git flow feature start my-feature |
git checkout -b feature/my-feature develop |
Pushes the feature branch to the remote server
gitflow | git |
---|---|
git flow feature publish my-feature |
git checkout feature/my-feature |
git push origin feature/my-feature |
Pulls the feature branch from the remote
gitflow | git |
---|---|
git flow feature pull origin my-feature |
git checkout feature/my-feature |
git pull --rebase origin feature/my-feature |
Merges the feature branch into develop and ensuring a regular merge with no-fastforward is performed - only use when not creating a pull request for review
gitflow | git |
---|---|
git flow feature finish my-feature |
git checkout develop |
git merge --no-ff feature/my-feature |
|
git branch -d feature/my-feature |
gitflow | git |
---|---|
git flow release start 1.2.0 |
git checkout -b release/1.2.0 develop |
gitflow | git |
---|---|
git flow release publish 1.2.0 |
git checkout release/1.2.0 |
git push origin release/1.2.0 |
gitflow | git |
---|---|
git flow release finish 1.2.0 |
git checkout main |
git merge --no-ff release/1.2.0 |
|
git tag -a 1.2.0 |
|
git checkout develop |
|
git merge --no-ff release/1.2.0 |
|
git branch -d release/1.2.0 |
gitflow | git |
---|---|
git flow hotfix start 1.2.1 [commit] |
git checkout -b hotfix/1.2.1 [commit] |
gitflow | git |
---|---|
git flow hotfix finish 1.2.1 |
git checkout main |
git merge --no-ff hotfix/1.2.1 |
|
git tag -a 1.2.1 |
|
git checkout develop |
|
git merge --no-ff hotfix/1.2.1 |
|
git branch -d hotfix/1.2.1 |
Pull requests should be used for merging most feature branches.
As a general rule, on the completion of a pull request, use the Merge type
of Merge (no fast forward)
and avoid Squash and Rebase merges unless the impact is full understood. Gitflow helper **git flow feature finish my-feature**
does this automatically for you.
We should ensure Semantic Versioning throughout our applications, services and packages. The format should be [Major].[Minor].[Patch].[BuildNumber][BuildSuffixTag]
• Major - indicates a breaking change has been made and the client will have to change in order to use the new version of the service. Major releases are infrequent and slower to deploy
• Minor - indicates that minor features or significant fixes have been added
• Patch - indicates a minor bug fix or any other insignificant changes
• BuildNumber - indicates the incrementing ID from our Build Server.
• BuildSuffixTag - optional - signifies it's not a production build / release and differentiate different builds off the same branch.
Feature branches and the develop branch build will have either an
-alpha
or-preview
suffix (e.g.2.6.0.123-alpha
).Release branches and hotfix branches should always build release candidate branch build will have an
-rc
suffix (e.g.2.6.0.123-rc
).
main
branch should always build unqualified versions - versions without build numbers (e.g.2.6.0
).
Here'’'s what to build from which branch.
Feature branches and the develop branch should always build -alpha
versions (e.g. 2.6.0.123-alpha
).
Release branches and hotfix branches should always build release candidate versions (e.g. 2.6.0.123-rc
).
The main
branch should always build unqualified versions - versions without build numbers (e.g. 2.6.0
).
Please remember:
When you create a new branch, you need to manually update the software’s version number.
If you’re using RPM, you need to put the buildNo part of the version number into the release tag in your spec file (or add a release tag to the configuration section if you’re using Maven’s RPM plugin). What You Should Install Where
As a rule of thumb …
-
-alpha
versions should only be installed on dev boxes and integration environments. They shouldn’t be deployed to any of the dedicated test environments. -
-rc
version should be installed in the dedicated test environments. In an emergency, a release candidate can be installed into the production environment. -
Production
releases can be installed anywhere - and they are the only kind of build that should be installed into the production environment.
All builds should be defined in a azure-pipelines.yml
that is on the root of main
when using Azure DevOps Pipelines.
The yaml file should begin with the defined triggers:
trigger:
- main
- develop
- feature/*
- bugfix/*
- hotfix/*
- release/*
steps:
- task: le-first-build-task@2
displayName: 'Parse RELEASE_NOTES.md'
inputs:
releaseNotesFilename: './release_notes.md'
semverOutputVariable: 'LE_BuildNumber'
- task: PowerShell@2
displayName: 'Is Alpha Build?'
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/heads/rc/')))
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[build.updatebuildnumber]$(LE_BuildNumber).$(revision)-alpha"
Write-Host "Build.BuildNumber: $(Build.BuildNumber)"
- task: PowerShell@2
displayName: 'Is Release-Candidate Build?'
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/rc/'))
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[build.updatebuildnumber]$(LE_BuildNumber).$(revision)"
Write-Host "Build.BuildNumber: $(Build.BuildNumber)"
Updated to use default standard naming convention
Branch name for production releases: [main]
Branch name for "next release" development: [develop]
How to name your supporting branch prefixes?
Feature branches? [feature/]
Bugfix branches? [bugfix/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []