Build the mental model
Every team eventually needs an explicit answer to a simple question: what do branches actually mean here, and when does code reach main? Four common strategies answer it differently, and the right choice depends far more on team size and release cadence than on which is technically fancier.
| Strategy | Best for |
|---|---|
| Trunk-based development | Small teams with strong CI and feature flags, committing directly or via very short-lived branches straight to main. |
| Feature branching | A low-level convention any team can use — isolate each unit of work on its own branch until ready, without committing to a particular release process. |
| GitHub Flow | Most modern web teams shipping continuously — branch off main, open a PR early, review, merge, deploy from main. |
| Git Flow | Software with scheduled, versioned releases needing multiple supported versions at once — adds develop, release, and hotfix branches. |
GitHub Flow maps naturally onto GitHub's pull request tooling and is a strong default for most teams. Git Flow's extra ceremony pays off for packaged applications or embedded firmware where multiple versions must be supported simultaneously, but it's usually overkill for a small team shipping a web app every day.
GITHUB FLOW: THE DEFAULT FOR MOST MODERN TEAMS
----------------------------------------------
main -------o------------------------o------> (deployable)
\ /
branch (feature/x)
\--commit--commit--/
|
open PR, review,
checks pass, merge
Git Flow adds more structure on top of this: a long-lived
develop branch, dedicated release branches, and separate
hotfix branches -- useful for scheduled, versioned releases.Connect it to a real scenario
This example demonstrates the GitHub Flow naming convention in a real repo: after an initial commit on main, git checkout -b feature/user-authentication creates a new branch directly off main, named to describe the work rather than the person doing it.
Branch off main
git checkout -b feature/user-authentication switches onto a new branch; git branch --show-current confirms it, and git branch lists both with an asterisk on the active one.
Open a PR early
Push the branch and open a pull request against main as soon as there's something reviewable, even before the work is finished, so teammates can weigh in early.
Merge and deploy
Once checks pass and a reviewer approves, the branch merges into main and, in a continuous-deployment setup, main deploys automatically.
Delete the branch
GitHub Flow branches are meant to be short-lived, typically merged within days; there's no develop, release, or hotfix branch, because main is always assumed deployable.
Try the working example
export GIT_AUTHOR_NAME="Thuta Learner"
export GIT_AUTHOR_EMAIL="learner@example.com"
export GIT_COMMITTER_NAME="Thuta Learner"
export GIT_COMMITTER_EMAIL="learner@example.com"
git init
export GIT_AUTHOR_DATE="2026-01-01T09:00:00"
export GIT_COMMITTER_DATE="2026-01-01T09:00:00"
echo "v1" > app.js
git add app.js
git commit -m "Initial commit on main"
git checkout -b feature/user-authentication
git branch --show-current
git branchgit branch --show-current prints:
feature/user-authentication
git branch lists both branches, with an asterisk marking the active one:
* feature/user-authentication
main5-minute try-it
For a small team shipping a web app daily, decide between trunk-based development and GitHub Flow and write down why. Then imagine the same team building desktop software with quarterly releases that need long-term support for older versions — would Git Flow's extra branches now be worth the overhead? Justify both answers.
One important caution
Adopting Git Flow's full branch structure for a small, fast-shipping team adds process overhead that slows releases down without buying any real safety.
Letting a GitHub Flow feature branch live for weeks instead of days defeats its purpose — long-lived branches drift far from main and produce painful merge conflicts.
GitHub Docs - GitHub flow — Git & GitHub