Most production applications rely on a team of software developers where each developer can focus on developing different aspects of the application in parallel. Using version control systems like Git and online source repositories like GitHub, team members can manage code changes from each developer, resolving conflicts as needed.
This makes managing code changes easier, facilitates collaboration, and speeds up application development times. However, managing code changes can become a real mess without a solid branching strategy. In this piece, I’ll share more about branching strategies, why you need one, and some of the different branching strategies you’re likely to encounter.
Let’s get started!
In Git, "branching" refers to the process of creating a new line of development that diverges from the main line of development. Essentially, it allows you to create a separate version of your code, make changes independently of the main version, and then merge those changes back into the main version when you're ready.
Branching strategies are the ways in which developers manage their interactions with the central codebase. There are three different types of branching strategies commonly used by teams to manage their codebase: feature branching, release branching, and trunk-based development (TBD).
You'll learn more about each of these later in this article, but first, let's discuss why you need a branching strategy.
Having a branching strategy is important, especially for large development teams, because they enable the following:
Parallel Development: Large teams often work on multiple features or issues simultaneously. Having a branching strategy allows team members to work on their specific tasks without interfering with each other's work.
Isolation of Changes: When multiple developers work on the same codebase simultaneously, there is always a risk of conflicting changes. Branching allows developers to work on their own isolated changes, reducing the risk of merge conflicts and other issues.
Risk Management: Branching also allows teams to manage risks associated with new features or changes. For example, a team can create a separate branch for a new feature, test it thoroughly, and then merge it back into the main branch when it's ready. This reduces the risk of introducing bugs or other issues into the main codebase.
Code Quality: A branching strategy can also help maintain code quality. By enforcing processes around code reviews, testing, and merging, teams can ensure that code changes are thoroughly reviewed and tested before they are merged into the main branch.
Release Management: A branching strategy can also help with release management. Teams can create a separate branch for each release, allowing them to isolate changes and bug fixes for that specific release. This makes it easier to manage releases and ensure that the correct changes are included in each release.
Let’s take a look at each branching strategy mentioned above and how it works in practice:
In a feature branching strategy, developers create a feature branch from the main branch specifically for developing a new feature or bug fix. A feature branch is often synonymous with a user story on a project management board. Once the developer working on a feature branch completes the feature, the branch is merged into the main branch. Typically, the feature branch is deleted after merging.
A feature branching strategy allows developers to work independently of new features while keeping the main branch stable. In addition, it allows teams to innovate and experiment. For instance, since developers aren't working directly on the main branch, they can experiment and implement new things on the feature branch. If it doesn't work as expected, the branch can easily be discarded without affecting the main branch.
When a developer works on a feature branch for a long time, it increases the chances of conflicts when merging the feature branch with the main branch. This means developers will often spend time fixing issues before they can merge their features back into the main.
However, there are ways to get around this:
Developers may limit the length of time they can keep a feature branch open. The longer a feature branch exists, the higher its chances of it becoming stale.
Developers can update the feature branch with changes from the main branch periodically.
It's important to note that if any fix is needed urgently after a feature has been deployed on production, the developer will have to create a separate branch called a hotfix branch or, in a worst-case scenario, revert the whole feature deployment. The only difference between a hotfix branch and a feature branch is hotfixes are usually deployed within hours as opposed to days.
The release branching strategy is a branching strategy that is suitable when teams want to coordinate the release of features into the production environment. Unlike the feature branching strategy, where each feature merged into the main indicates that it's ready for production, in the release branching strategy, a release branch is created from the develop branch. The develop branch is a separate branch created from the main branch solely to contain all newly developed code features; this is the branch where new feature branches are created.
Once the feature branch is tested and completed, the branch is merged into the develop branch. Then, once the develop branch has enough features for a release, a release branch with a version tag is created from the develop branch.
Once the release branch is tested and all bugs found on the release branch have been fixed, then the release is merged into the main branch. Often, the release branch is deleted after merging.
A release branching strategy is useful for managing deployment for specific times and dates, and it allows for production releases to be more organized.
Because features are not merged immediately into main, features may take longer to get into production. This problem gets worse if you have a big team of developers working on a lot of features simultaneously. To avoid delays, you should plan releases for a short period, ideally every 1-4 weeks. If you need to fix something urgently after deploying a release branch on production, you'll again have to use a hotfix branch or revert the entire deployment.
A trunk-based strategy (TBS) encourages developers to make small updates frequently to the main branch instead of having long-lived feature branches. This means that changes happen very frequently, which typically reduces the challenge of merge conflicts.
The biggest advantage is that the main branch is always in a release state which means that the code in the main branch can be pushed into production at any time. Additionally, there tend to be fewer merge conflicts due to the usage of short-lived branches.
In addition, code reviews must be done quickly, making it easier to spot bugs as changes are done in smaller batches.
The main problem with this strategy is that there is a tendency to merge unfinished work into the main branch. To prevent any issues with this, your team can incorporate feature flags, which disable the code for a particular feature from running in production until the feature is completed.
Another possible problem with the TBD strategy is that bugs are more likely to slip into the main branch because of the high rate of code changes. To ensure that there are fewer conflicts, it’s important that your team has a strong code-review process and testing strategy in place.
Choosing the right branching strategy is essential for your team's development workflow. In this article, you learned about different types of branch strategies and how to circumvent the disadvantages of each.
It's important to note that there isn't a "best" or "worst" branching strategy. Determining the best branching strategy boils down to your team’s preferences and how each might fit into their workflow. If you’ve used any of these strategies or you have your own suggestions to improve them, tell me about them in the comments or on Twitter.