Git Course 0%

Feature, bug-fix, hotfix, release workflows

Intermediate ≈ 14 min

Before this lesson

What you will learn

  • What distinguishes the four flows, and why only one of them is unusual
  • Where each branch starts and what it merges into
  • How a hotfix reaches both the release and main

After this lesson you can

  • I can recognize which kind of work I am doing and follow the right route

Why this matters

Most work follows the same route, which is why lesson 13.1 is enough for the majority of days. The exceptions matter because they arrive under pressure: a hotfix at four in the afternoon is not the moment to work out where the branch should start.

The four flows

Feature, bug fix, hotfix and release flows Four rows, each a branch line. Feature: branch from main, several commits, merge request, merge back into main; days. Bug fix: the same shape but shorter, usually one or two commits, and the issue number is in the branch name; hours to a day. Hotfix: branch from the release tag rather than from main, one commit, merge to main and also to the release branch, then a new tag; minutes to hours, and it interrupts everything. Release: branch or tag from main when a version is ready, with only fixes going onto it while main carries on. Each row names where it starts and where it ends. Feature branch from main · several commits · merge request · squash into main · days main merged Bug fix same shape, shorter · one or two commits · issue number in the branch name · hours Hotfix branch from the released tag, not from main · one commit · merge to both · re-tag · minutes v1.2.0 also onto release/1.2, then tag v1.2.1 Release cut from main when a version is ready · only fixes go onto it · main carries on cut here release/1.2 — fixes only main Only the hotfix starts anywhere other than main, and that single difference is what makes it feel unfamiliar when you meet one.
Only the hotfix starts somewhere other than main, which is the single thing that makes it feel unfamiliar.

Feature

Starts from: current main. Ends at: main, through a merge request. Lives: days.

Terminal
$ git switch main && git pull
$ git switch -c feature/21-difficulty-filter
# work, commit, push, merge request

The only discipline that matters is size. A branch that lives two days and touches five files gets reviewed in twenty minutes; one that lives three weeks gets reviewed badly, or not at all. If a feature is genuinely large, split it into several merge requests that each work on their own.

Bug fix

Starts from: current main. Ends at: main. Lives: hours.

Terminal
$ git switch -c fix/15-empty-distance

Structurally identical to a feature, with two differences in practice: the branch name says fix, and the merge request should say how to reproduce the bug and how you verified it is gone. That second part is what lets a reviewer, or a tester, confirm the fix rather than take your word for it.

Hotfix

Starts from: the released tag or release branch, not from main. Ends at: both the release and main. Lives: minutes to hours.

This is the one that is different, and the reason is simple: main has moved on since the release. Whatever is broken in production is broken in v1.2.0, and main may contain a dozen changes that are not ready to ship. So you start where production is:

Terminal
$ git fetch --tags
$ git switch -c hotfix/23-wrong-region-name v1.2.0
# one small commit
$ git push -u origin hotfix/23-wrong-region-name

Then it has to reach two places:

  1. Into the release: merge request onto release/1.2 (or onto the branch your team ships from), then tag v1.2.1 and release (lesson 13.6).
  2. Into main: a second merge request, or a cherry-pick (lesson 13.5). Skipping this is how a bug gets fixed in production and comes back in the next version.

That second step is forgotten often enough to be worth a checklist item in your team's hotfix process.

Release

Starts from: main, at the point a version is ready. Ends at: a tag, and possibly a long-lived branch. Lives: as long as the version is supported.

Two shapes, and which one your team uses decides how hotfixes work:

Shape How it works Suits
Tag only Tag main as v1.3.0 and ship it; the next release is the next tag Web services, continuous deployment
Release branch Cut release/1.3 from main; only fixes go onto it, while main carries on with new work Software with supported older versions

With a release branch, the rule that keeps it sane is: nothing new goes onto it. Every change on a release branch is a fix that also exists on main.

Which one am I doing?

Question Answer
Is production broken right now? Hotfix
Does it fix behaviour that was supposed to work? Bug fix
Does it add or change intended behaviour? Feature
Am I packaging what already exists into a version? Release

If it is a hotfix and you are unsure where to branch from, ask before branching. It is the one case where starting in the wrong place costs real time.

How to do it

The only command that differs between the flows is the one that starts the branch:

Terminal
$ git switch -c feature/21-difficulty-filter          # from current main
$ git switch -c fix/15-empty-distance                 # from current main
$ git switch -c hotfix/23-wrong-region-name v1.2.0    # from the released tag

For the last one, git fetch --tags first; tags do not arrive with an ordinary fetch of branches unless they are on fetched history.

Common mistakes

  • Branching a hotfix from main, which ships everything else on main along with the fix.
  • Fixing production and forgetting main, so the bug returns in the next release.
  • Putting new features on a release branch, which turns it into a second main.
  • A feature branch that lives three weeks. Split it.
  • A bug-fix merge request that does not say how to reproduce the bug, leaving the reviewer unable to verify anything.
  • Tagging before the pipeline is green. The tag is a promise about a state.

Try it yourself

Goal: do a hotfix properly, including both destinations.

  1. In your practice project, tag main as v1.2.0 and push the tag.
  2. Add two ordinary commits to main, so it has moved on.
  3. Create hotfix/23-wrong-region-name from the tag, not from main, and make a one-line fix.
  4. Merge it into a release/1.2 branch cut from the same tag, and tag v1.2.1.
  5. Get the same fix onto main, by merge request or cherry-pick.
  6. Check with git log --oneline v1.2.0..v1.2.1 that the release contains only your fix.

Expected result: a release containing exactly one change, and main containing the same fix, reached by two routes from one branch.

Show solution

Step 6 is the check that the hotfix was branched from the right place. If the range shows your two unrelated commits from step 2, the branch started from main and the release contains work that was never meant to ship. That is the entire reason hotfixes branch from the tag.

Check yourself

1. Where does a hotfix branch start?
2. After a hotfix is merged into the release, what else must happen?
3. What rule keeps a release branch usable?

Key terms

Branch Hotfix Release Tag main