Git itself doesn't enforce any particular way of organizing branches - everything in this guide is a convention, agreed on by a team, not a rule Git imposes. Different conventions suit different release schedules and team sizes, which is exactly why multiple competing ones still exist.
Trunk-based development
Everyone commits to (or merges very short-lived branches into) a single main branch, often multiple times a day. Work that isn't finished yet is hidden behind feature flags rather than kept on a long-lived branch. This keeps branches small and conflicts rare almost by construction - there's simply never enough time for a branch to drift far from main before it's merged back.
- Best for: teams with strong CI/CD and automated testing, continuous deployment, and a culture of small, frequent commits.
- Tradeoff: requires discipline around feature flags and a genuinely reliable test suite - without those, shipping unfinished work to main gets risky fast.
Git Flow
A much more structured model with dedicated long-lived branches for different purposes: main (production-ready releases only), develop (integration branch for ongoing work), feature/* branches off develop, release/* branches for release preparation, and hotfix/* branches for urgent production fixes applied directly to main. It gives every kind of change an explicit home, at the cost of real process overhead.
- Best for: teams shipping versioned software with scheduled releases - desktop apps, embedded firmware, anything where "release 2.4.0" is a meaningful, discrete event.
- Tradeoff: a lot of ceremony for a team that deploys continuously; the extra branches solve problems a fast-shipping web team usually doesn't have.
GitHub Flow (the common middle ground)
A simpler alternative that's become the default for a lot of web teams: just main plus short-lived feature branches, each opened as a pull request, reviewed, and merged (or squash-merged) back into main, which deploys automatically or near-automatically. No develop branch, no release branches - main is always deployable.
- Best for: web applications and services with continuous deployment and a PR-based review culture.
- Tradeoff: assumes you can deploy main safely at any time, which again comes back to test coverage and CI confidence.
Trunk-based keeps everything flowing through one branch constantly. Git Flow gives each kind of work its own longer-lived branch, at the cost of more structure to maintain.
How to actually choose
Three questions get you most of the way there: How often do you release - continuously, or on a schedule? How mature is your automated testing - can you trust main to always be deployable? And how big is the team - does a lightweight convention hold up, or does more structure prevent chaos? Smaller teams shipping continuously tend to drift toward trunk-based or GitHub Flow by default; larger teams or those shipping versioned, installable software tend to need Git Flow's extra scaffolding.