Branching strategies, releases and versions
How a team uses branches decides how often it can ship and how calmly it can fix a bug in the busiest week of the year. This lesson compares the three common strategies, shows how rulesets turn your agreements into rules GitHub enforces, and walks through tags, releases, version numbers and a hotfix from start to finish.
By the end you can
- Explain GitHub flow, Git flow and trunk-based development, and pick one for a small team
- Set up a ruleset for
mainin the UI and withgh api - Choose version numbers with semantic versioning, for an app and for a library
- Tag a release, publish a GitHub Release with notes, and ship a hotfix with cherry-pick
- Map branches and tags to dev, staging and production
The everyday picture
Think of two ways to organise traffic in a busy city like Dhaka, Lagos or Jakarta. In the first, there is one wide main road. Motorbikes and cars join it from short side lanes, a few metres long, and merge back quickly. Traffic keeps moving because nobody stays in a side lane for long. In the second, there is a large junction with flyovers, U-turns and separate lanes for buses, trucks and private cars. It can handle many kinds of traffic, but every driver needs a map, and one wrong turn costs twenty minutes.
Branching strategies are the same choice. Short side lanes into one busy main road is GitHub flow and trunk-based development. The complicated junction is Git flow. The junction is not wrong, but it only pays off if you really have that many kinds of traffic.
Three strategies and what each one costs
GitHub flow has one long-lived branch, main, which is always deployable. Every change starts as a short branch from main, goes through a pull request with review and checks (see Pull requests and code review), and merges back. You deploy from main, often right after each merge. Branches live for hours or a few days.
Trunk-based development pushes the same idea further. Everyone merges into main (the trunk) at least once a day. Unfinished features are merged too, but hidden behind a feature flag, so the code is on main while stores and customers do not see it yet (see Shipping safely: containers, CI/CD and releases). It needs good automated tests, because there is very little time between a merge and production.
Git flow keeps two long-lived branches. develop collects finished features; main only holds released versions. To ship, you cut a release/1.5 branch from develop, test and fix it there, then merge it into both main and develop. Urgent fixes start from main on a hotfix/ branch and are also merged into both. It fits software that ships numbered versions on a schedule and must support several of them. Its author added a note in 2020 suggesting that teams shipping web apps continuously adopt a simpler workflow such as GitHub flow.
The cost of long-lived branches is merge pain that grows with time. Two branches that drift apart for three weeks produce conflicts in files nobody remembers changing (see Merge conflicts without panic). Short branches keep conflicts small and keep main close to what is in production.
Quick check
A team deploys its back-office dashboard several times a day and has good automated tests. Which strategy fits best?
Frequent deploys and good tests are exactly what short branches into one main need. Git flow adds a slow path to production that this team does not need, and long-lived personal branches produce the drift and merge pain the strategies try to avoid.
main and come back within days, and main is always deployable. Git flow: features merge into develop; a release branch is cut, tested and merged into both main (tagged) and develop; hotfixes start from main and go back into both.| Strategy | Good for | Watch out |
|---|---|---|
| GitHub flow | Web dashboards and APIs deployed often; small teams; the easiest to learn | Needs CI and review on every PR, because main goes to production |
| Trunk-based | Teams with strong tests that want to deploy many times a day | Needs feature flags and discipline; a broken trunk blocks everyone |
| Git flow | Versioned products with planned releases and several supported versions | Long-lived branches drift; double merges; slow path to production |
| GitHub flow + release branches | Mobile apps such as store-app, where a build goes out to devices and needs patching | Every fix on a release branch must also reach main |