A branching strategy refers to the strategy a software development team employs when writing, merging, and shipping code in the context of a version control system. The goal of any branching strategy is to solve that problem and to enable teams to work together on the same source code without trampling on each other. A branching strategy defines how a team uses branches to achieve this level of concurrent development. A branching strategy ensures everyone on the team is following the same process for making changes to source control. The right strategy enhances collaboration, efficiency, and accuracy in the software delivery process, while the wrong strategy (or no strategy) leads to hours of lost effort.
Common types of branches
We cannot talks about branches strategies without know about types of branches. So, here a brief overview:
Every Git repository has a trunk (also referred to as main, mainline, or the master branch). When a Git repository is created, the trunk exists automatically as the implicit first branch. The use of a trunk and the timing of changes landing on it vary depending on the exact branching strategy being used
The development branch is a long-lived feature branch that holds changes made by developers before they’re ready to go to production. It parallels the trunk and is never removed. Some teams have the development branch correspond with a non-production environment. As such, commits to the development branch trigger test environment deployments.
A feature branch can be short- or long-lived depending on the specific branching flow. The branch often is used by a single developer for only their changes, but it is possible to share it with other developers as well.
In the release branch reflects a set of changes that are intended to go through the production release process.
A hotfix branch is a branch that’s used generally to hold changes related to emergency bug fixes. They can be short-lived or long-lived, though generally they exist as long-lived branches split off from a release branch.
Most common branching flows
Trunk Base Development Branching Model
This strategy uses the main branch as mainline development, it is where all developers commit. In this model developers usually clone branches and make changes locally so push them to the main line ( bugfix, feature, etc…) Teams that use this strategy should to have high \ maturity, strong automation and test a lot before pushing any code to the main line. In trunk-based development, the trunk is the central branch to which all developers send their code changes. All developers integrate their changes directly to a shared trunk every day,a shared trunk that is always in a releasable state. No matter what a developer might do on their local repository, at least once each day, they must integrate their code. We can use Trunk Base Development as a branching policy alternative to gitflow and github Flow.
Also in this model, it is possible developers and release engineers branch but when it is absolutely necessary. . If they do, they create a short lived feature branch that is merged back into the master after being tested. trunk-based development is a prerequisite for CI/CD, it truly enables those modern delivery approaches. It enables continuous integration front and center in a developer’s workflow having to integrate your changes every day. Integrating changes every day means that you must take small steps forward. You cannot start your work by making a sweeping set of changes in a lot of code files that breaks your local compilation.
We know that the goal of DevOps teams is to test and build often, continuously integrating, testing, and delivering code back to developers ensures that teams detect failures fast, and resolve issues quickly. But, there is a challenge when a feature is so big to finish in one day…The solution is a practice called branch by abstraction that helps developers to continue integrating small changes every day even if the overall feature still takes several days to complete. As such, you will find some point in your code where you can toggle over to different logic. It enables toogled feature or feature flags that enable your changes to go to a non-production environment for verification, but not yet be visible in production or maybe you want to enable canary, A/B testing for a set of users.
- truly Continuous Integrations
- small changes
- feature flags
- branch by abstraction
- contention collision
- more complex
- desired High team maturity
- strong automation
- test a lot before push
Example flow: ( Developer needs to create a new feature or bug fix )
- developer creates a new branch from trunk branch ( checks out the trunk branch, pulls changes, and then creates a new branch )
- the developer create a feature or fix a bug
- developer creates a pull request to the trunk branch ( usually include a git tag that identifies their changes )
- another developer reviews their code and verifies the feature or fix, so they approve the pull request
- the developer merges the code to trunk and verifies that it works in an integration environment.
- their tag is promoted to the QA environment. This tag deploys some new code for the QA team, which they’re able to quickly verify
- the QA team promotes that tag to the user acceptance environment
- the operations team verifies the requirements are satisfied and they promote the tag to the production system
- An automated system takes the tag, checks out the code, builds it, and deploys it
GitFlow Branching Model
Git flow was one of the first proposals to use git branches. Gitflow helps with continuous software development and implementing DevOps practices.
Instead of a single main branch, this workflow uses two long active branches to record the history of the project usually known as master branch( main/production branch ) and development branch. Gitflow has a master branch and a separate develop branch as well as supporting branches for features, releases and hotfixes. The development happens on the develop branch, moves to a release branch and is finally merged into the master branch.
The main branch stores the official release history and the develop branch serves as an integration branch for features. The code in the main/production branch should be most stable, instead of development branch, that is a live alongside branch where developers integrate their changes. Inside gitflow strategy, you can have multiple branches strategies like feature branches, hotfixes, and release branches deriving from the development branch or main branch.
To minimize the big challenge to merge into the main branch, the teams should have discipline and keep feature branches small and short-lived. The GitFlow is great for a release-based software workflow.
- usually ensures a clean state of branches at any given moment in the life cycle of project
- branch development is totally separated from the production ( main branch )
- the main branch is always or almost ready for release
- the branches naming follows a systematic pattern making it easier to comprehend
- gitflow offers a dedicated channel for hotfixes to production.
- Many branches can become difficult to manage
- features can take days to merge because a lot of changes committed to development branch without integrated, tested previously.
- long-lived branches, is a large maintenance headache for a team
- complex work process complexity
- slow feedback
- heavy branch overhead
Example Flow: (Developer needs to create a new feature, release a version or fix bug)
- A development branch is created from main branch
- Features branches are created from development branch
- When some of features branch or release branch are completed, they can merged to the development branch
- When need a release branch is created from development branch and when its done, it is merged to development and main branch
- If any issue in a main branch is detected, is created a hotfixed branch from main. Once its completed, it is merged to development and main branch.
Feature Branching or Github Flow Branching Model
A simpler strategy that keeping a main branch continuously deployable. A feature branch is created to work on any feature or bug fix. GitHub Flow can be considered a simplified model of GitFlow. This is very simple and clean, many organizations have adopted it with great success. Each feature branch must be finished and fully tested before being merged with the main branch. In the Feature branch we start with just one main branch and all branches are delivered from there. Generally we have short delivery cycles. Also, each developer creates a new branch for their changes from the trunk branch for a specific feature or task( main branch ).
Each Feature Branch can be deployed to a testing environment for tests or can be pushed to trunk base directly and then deployed a non production environment for verification and tests. Merging everything into the master branch and deploying often means you minimize the amount of code which is in line with the lean and continuous delivery best practices.
It is generally used for small teams because they don’t need to manage multiple environments and versions. A short-lived release branch may be used off-trunk to prepare for and execute a release. The branch management is less than other strategies because we have only a long-lived branch, the main branch. To enable the feature branch, you’ve to support Continuous Integration regularity as well as Continuous Delivery. As the team grows it is important to integrate changes across teams frequently.
Everything you need to do you have to pull request, not only when you finish some feature, but for all, including when you need feedback, for instance.
- lightweight workflow
- work well with CI/CD
- small teams can build, test and deploy features fast
- developers leads on small sets of changes instead of entire release
- simple work process complexity
- each team or sub-team could maintain their own branch for development
- light branch overhead
- fast feedback
- clean History
- the merge to main branch need to be done carefully because the risk of being unstable.
- as your teams grow, this model can cause costly merge conflicts
- as have many branches the complexity is growing
Example Workflow (Developer needs to create a new feature)
- Developer will begin a new feature
- The developer checks out a branch based on main branch
- Developer starts to work in a feature with many commits as necessary
- During the featuring development, the developer should keep up to date their changes to a central repository
- As soon as the developer finish the feature, before merging it into main, developer makes a pull request asking to merge into the main branch
- If another developer that reviewed the pull request wants to make some changes before integrating the main branch, they will work together, or not, and all the changes will be shown in pull request, if approved now, one of them will make a merge commit into the main branch.
Forking Workflow Model
Forking workflow is almost the same as the feature branch but it does not create the branch for developing some features, it forks the repository. This means that complete feature branches will be purposed for merge into the original project maintainer’s repository providing a very flexible way to contribute, making it an ideal workflow for open source projects. Forking model uses a single server side repository as the central code base and the developers have their own repository. Each developer has two Git repositories: a private local repository and a public server side repository.
As said, the forking workflow typically is most often used in public open source projects. Contributions can be integrated without the need for everybody to push to a single central repository. Developers push to their own server-side repositories, and only the project maintainer can push to the official repository. This allows the maintainer to accept commits from any developer without giving them write access to the official codebase.
- contributions can be integrated without the need for everybody to push to a single central repository
- helps a maintainer of a project open up the repository to contributions from any developer without having to manually manage authorization settings for each individual contributor
- do not deal with permissions
- very specific usage
- delivery process is very slower than another strategies
Example Flow:(Developer needs to create a new feature)
- developer forks an official server side repository. It created a server-side copy on his repository and then clone his copy to a local repository
- now there is a git remote path for the official repository in the local clone
- developer creates a new local feature branch
- developer works in his changes and commit it
- now the branch gets pushed to the developer’s server-side copy
- then the developer opens a pull request from the new branch to the official repository.
- if the pull request gets approved for merge it is merged into the original server-side repository
- Usually there is a official code base where the maintainer pulls the contributor’s changes into their local repository and merges it into their local main branch, then pushes the main branch to the official repository on the server.
Release Branch Strategy is commonly used for teams that need to support multiple releases and patch versions over time. If you are working on a product that needs to support multiple versions in parallel or needs to handle customization for a specific customer, release branching is a requirement. It allows your team to focus on specific issues per patch or release. When the version needed to be developed in many models of industrial machines for example, each machine had many software versions for which it had to guarantee stability and efficiency because of the important performance and reliability requirements of production lines.
For all potential releases the new branch is created and the team starts to work. It’s common to use different branch strategies when a branch is created like feature branch, hotfix and so on … the important thing is that all branches are released. This method is certainly open to any type of customization according to the preferences of the working group. Generally is bringed up each release for each team.
- Required for teams that support multiple version
- Every release is perfectly traceable
- The team can work independently on every release
- The development of a release is very neat and respectful of all good practice of software development
- usually no automation
- no continuous ANYTHING
- usually associated with low frequency deployment
- communication between the team is complex
- merge is complicated
Example Workflow:(Team plans to bring up new release)
- The Team plans to bring up a new release
- Someone in the team should create new branch for that release
- Developers checkout that branch (downloading and track the branch) created to working locally
- Every feature, task or everything else from release planning backlog should be developed. Any new ideas should go in the backlog for a future release.
- Any bugfix should de pushed as soon as possible on the master branch
- Once finished, the developers should update your local branch and then ask for a merge request.
This strategy is like an extension of GitHub Flow with master and feature branches, however, it adds environment and release branches. It is a simple alternative to gitflow and it merge feature driven development and feature branches an issue tracking system. The most difference between GitLab Flow and GitHub Flow are the environment branches having in GitLab Flow (e.g. staging and production) because there will be a project that isn’t able to deploy to production every time you merge a feature branch. GitLab Flow offers a simple, transparent, and effective way to work with git, developers can collaborate and maintain several versions of software in different environments decreasing the overhead of releasing, tagging, and merging. An environmental branch is branch that contains commits that apply to the source code to reconfigure the product to run in a differents environments.
Gitlab flow uses feature branches rather than direct commits on the main branch, there is no commit direct on master. The All code reviews and tests are run in all commits and stages, not only on master. All features and fixes go to the main branch while enabling production and stable branches including a set of best practices and guidelines. The deployment are automatic and based on branches tags, releases are based on tag too.
- truly define Continuous Integration and Continuous Delivery
- offers a simple, transparent, and effective way to work with git
- developers can collaborate on and maintain several versions of software in different environments
- simple work process complexity
- high frequency deploy
- fast feedback
- clean History
- It is more complex than GitHub Flow
Example Workflow: (Developer needs to develop new feature )
- developer creates your own branch ( Switch to master branch then pull all changes and finally create a feature branch
- developer staging your branch ( git add and commit changes )
- developer integrating his feature branch into environment branches
- usually CI/CD is used to deploy in developer, staging, tests and production environment
Branching best practices for all branching strategies
Here some tips for any strategy you choose:
communicate your branching strategy for your entire team and keep communication clean and up to date;
track your dependencies. Your team needs to be cleared about which areas or team will be affected when the new branch is created or plan to be released;
merging often reduces the risk that something breaks and review your merge and integration process;
Which strategy should you use?
The best version control branching strategy depends on the type of project and the size, structure, experience of your team, but the main to keep in mind is to stay simple and keep it simple until the project reaches a point where additional complexity is needed. So, to start small or for the early stages of most projects I think the best strategy is starting to use gitHub flow or trunk based development because most teams require only a single version of a release to be maintained. However, at the end, you decide !
I hope this post was useful.