All explainers

Gitflow, watched one branch at a time

5 min+15 XP

Gitflow is not a Git command. It is a set of rules about where a branch is allowed to start, and where it must go back to.

Git lets you branch from anywhere and merge into anything. That freedom gets messy fast on a team. Gitflow picks five kinds of branch and fixes the arrows between them, so nobody has to guess.

The five branches

Two branches live forever:

  • main: what is running in production right now. Every commit here is something real users have.
  • develop: the next release, being built. It is always ahead of main.

Three kinds of branch are short-lived. You make them, use them, merge them, and delete them:

  • feature/*: one new thing. Starts from develop, goes back to develop.
  • release/*: getting ready to ship. Starts from develop, goes to main and back to develop.
  • hotfix/*: a production bug that cannot wait. Starts from main, goes to main and back to develop.

The two "and back to develop" rules are the ones people forget. Watch what they do below.

The normal path: a feature becomes a release

From a feature branch to a tagged release

1 / 7
mainreleasedevelopfeatureM0D0maindevelop

Two branches never go away. main is what is live. develop is what comes next.

Notice what the release branch really buys you. From the moment it is cut, two things happen at once: the release is being tested and fixed, and develop is already taking the next batch of features. Without it, the whole team has to stop and wait while one version is tested.

The emergency path: a hotfix

Production is broken. develop has three weeks of half-finished work in it, so you cannot ship from there. This is the one case where you branch off main.

Fixing production without shipping unfinished work

1 / 4
mainhotfixdevelopM1D1D2mainv1.0develop

Version 1.0 is live. develop has already moved on with new work that is not ready.

That last step is the classic Gitflow bug. The fix is live, everyone moves on, and three weeks later the release goes out and the same bug comes back. It was never in develop, so the new release simply does not contain it.

Where the arrows must point

This is the whole model in one table. If you remember nothing else, remember this.

BranchStarts fromMerges back intoLives for
feature/*developdevelopDays to weeks
release/*developmain and developDays
hotfix/*mainmain and developHours
developn/an/aForever
mainn/an/aForever

Should you actually use it?

Gitflow was designed for software that ships on a schedule and supports more than one version at a time: desktop apps, mobile apps, on-premise products. That is what all the ceremony is paying for.

Most web teams deploy several times a day. For them, develop becomes a second main that nobody trusts, and long feature branches drift far away from everyone else's work. Trunk-based development is the common alternative: short branches straight off main, merged within a day or two.

Same feature, two ways of working

1 / 3

Gitflow

mainreleasedevelopfeatureM0D0F1maindevelopfeature

The branch is cut from develop, which is one step away from main already.

git switch -c feature/x develop

Trunk-based

mainfeatureM0F1mainfeature

The branch is cut straight from main. There is nothing in between.

git switch -c feature/x main

One team, one feature, two sets of rules. Both start the same way, with a branch.

 GitflowTrunk-based
Long-lived branchesTwo: main and develop.One: main.
Where a feature startsFrom develop.From main.
How long a branch livesDays to weeks.Hours to a couple of days.
Getting to productionfeature → develop → release → main.feature → main.
Merge conflictsMore. Branches drift apart while they wait.Fewer. Everyone merges into the same place daily.
Supporting old versionsBuilt in: a release branch per version.Awkward. You need extra long-lived branches.
Best fitScheduled releases, versioned products.Continuous deployment, web services.
Needs feature flags?No: unfinished work hides on its branch.Yes: unfinished work sits in main, turned off.

Common mistakes

Branching a feature off main. You then merge into develop and drag along whatever was in main but not in develop. Always cut features from develop.

Forgetting the merge back into develop. Both release and hotfix have two arrows out of them. Missing the second one is how a fix goes live and then disappears in the next version.

Letting a feature branch live for a month. develop moves on without you. The merge at the end is no longer a merge. It is a rewrite. Merge develop into your branch regularly, or keep the branch small.

Committing straight to main. In Gitflow, nothing lands on main except a merge from release or hotfix. Protect the branch so the rule is enforced, not just agreed.

Cutting a hotfix from develop. It feels faster. It ships three weeks of untested work to production along with your one-line fix.

Remember this

  1. 1main and develop live forever. feature, release and hotfix are made, merged, and deleted.
  2. 2release and hotfix each merge into TWO places: main and develop. Missing the second one is the bug that brings old problems back.
  3. 3Features come off develop. Hotfixes come off main. That single difference is what keeps unfinished work out of production.
  4. 4Gitflow is built for versioned releases. If you deploy several times a day, trunk-based is usually the better fit.

Now try these questions