Git for Engineers — Level by Level›05 · Branching strategies and releases

Lesson 05 of 8 · Level 2 — Working in a team

Branching strategies and releases

Choose how a team branches and releases: trunk-based development, GitHub flow, GitFlow and release branches compared; tagging releases with semantic versions; and handling hotfixes without losing fixes between branches.

Practitioner
Key wordsbranching strategytrunk-based developmentGitHub flowGitFlowrelease branchesfeature flagsgit tagsemantic versioninghotfixcherry-pickchangelog

Why the strategy matters

How a team branches decides how often code integrates, how much merging hurts, and how quickly a fix reaches production. For platforms that deploy continuously, simpler is better.

A shared kitchen works best when everyone puts ingredients back on the main shelf quickly. If each cook hoards their own shelf for weeks, the day they try to combine everything is chaos.

The common strategies

Strategy How it works Fits Watch out for
Trunk-based Tiny branches (or direct commits) merged into main at least daily; feature flags hide unfinished work; main is always deployable Continuous delivery, strong CI, experienced teams Needs good tests and feature flags
GitHub flow Short-lived feature branch → pull request → merge to main → deploy Most web services and platform repos Same as trunk-based, just with PRs
Release branches Cut release/1.4 when stabilising; fixes flow main → release Products with supported versions, scheduled releases Every fix may need applying to several branches
GitFlow develop, feature/*, release/*, hotfix/*, main Boxed software with long release cycles Heavy; long-lived branches drift; rarely worth it for services

Recommendation for most infrastructure and service repositories: GitHub flow / trunk-based, deploying main through the pipeline, with release branches only where you genuinely support several versions at once.

Tags and semantic versions

Mark releases with annotated tags and semantic versions:

MAJOR.MINOR.PATCH     2.3.1
  MAJOR  breaking change        (clients must change)
  MINOR  new, compatible feature
  PATCH  compatible bug fix
$ git tag -a v1.4.0 -m "Release 1.4.0: order search, faster checkout"
$ git push origin v1.4.0
$ git log v1.3.0..v1.4.0 --oneline        # release notes source

Container images, Helm charts and Terraform modules should carry the same version as the tag that produced them, so anyone can go from a running artifact back to the exact source.

Hotfixes without losing fixes

The rule that prevents regressions: fix forward on main first, then carry the fix to older branches.

$ git switch main
# fix, PR, merge -> commit 7c1d2e3
$ git switch release/1.4
$ git cherry-pick -x 7c1d2e3        # -x records "cherry picked from commit 7c1d2e3"
$ git tag -a v1.4.1 -m "Hotfix: order 404"
$ git push origin release/1.4 v1.4.1

If the fix had to be made on the release branch first (production is burning), open a pull request to bring it to main immediately, and check with git branch --contains <sha>.

Try it: a release and a hotfix

  1. In a test repo, make a few commits on main and tag v1.0.0.
  2. Create release/1.0 from the tag, add two more features on main, and tag v1.1.0 there.
  3. Fix a "bug" on main, cherry-pick it with -x onto release/1.0, and tag v1.0.1.
  4. Run git log v1.0.0..v1.0.1 --oneline and git branch --contains <fix-sha>.

Going deeper: release automation

Tools such as semantic-release or release-please read Conventional Commit messages (feat:, fix:, feat!:), decide the next version, write the changelog, tag and publish, removing human error from versioning. For GitOps repositories, the "release" is often a pull request that bumps an image tag or chart version per environment (see "GitOps Principles & Practice", lesson 03).

Recap

  • Prefer trunk-based / GitHub flow for services and infrastructure; release branches only for supported versions; GitFlow rarely.
  • Annotated tags with semantic versions; artifacts carry the same version.
  • Hotfix: fix on main, then cherry-pick -x to release branches, tag a patch release.

This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.