Trunk-based, GitFlow, GitHub Flow — and why simpler is usually better.
Trunk-based development takes the "branches should be short-lived" principle to its logical conclusion: branches live hours, not days. Engineers push small, incremental changes to main multiple times per day, using feature flags to hide incomplete work from users.
The advantages are real. Integration problems surface immediately because branches never drift far from main. CI runs are fast because the diff is small. There's no "merge day" because merging is continuous. Teams practicing trunk-based development report deployment frequencies 4–8× higher than teams using long-lived branches.
The requirements are also real. Trunk-based development demands excellent CI (tests must be fast and reliable), robust feature-flag infrastructure (you need to ship incomplete code safely), and high trust between engineers (no review gate means the author bears full responsibility). For a 4-person team with strong CI and a shared codebase, it's often the fastest way to work. For a 30-person team with spotty test coverage, it's a recipe for a broken main branch.
This is GitHub Flow taken one step further — fewer branches, shorter lifespans, more reliance on flags over isolation.
GitHub Flow is the right default for most teams, and it's worth understanding why. The entire model fits in three rules: main is always deployable, every change happens on a short-lived branch, and branches merge to main via reviewed PRs. That's it.
There's no develop branch, no release branch, no hotfix branch. One branch per change, one PR per branch, one merge to main. When main gets a new merge, you can deploy it — manually, automatically, or on a schedule. The simplicity is the feature.
GitHub Flow works because it matches how most product teams actually ship: continuously, in small increments, without the overhead of coordinating release trains. A feature branch lives for a day or two, gets reviewed, merges, and ships. If it breaks something, you revert and fix. The feedback loop is tight.
Where GitHub Flow struggles is when you need to maintain multiple production versions simultaneously (you ship v2.3 but need to patch v2.1 for a customer), or when your deploy process is slow and expensive (making "just revert" unrealistic). Those scenarios need a more structured branching model — but they're the exception, not the rule.
GitFlow was designed for a world where software shipped on CDs — versioned releases, long QA cycles, multiple supported versions in the field. If that's your world (desktop apps, embedded systems, enterprise software with contractual version support), GitFlow's structure earns its complexity.
The model adds several long-lived branches: develop (integration), release/* (stabilization), hotfix/* (emergency patches to production), and main (production state). Features branch from develop, releases fork from develop when a version is "feature-complete," and hotfixes branch from main directly.
For teams deploying a web application — which is most teams reading this course — GitFlow is almost certainly overkill. The develop branch adds a layer of indirection between your work and production without a proportional benefit. The release branches make sense only if you have a formal QA gate between "code complete" and "shipped." The hotfix branches are unnecessary when deploying a fix takes minutes, not weeks.
GitFlow isn't bad. It's designed for a specific context. If you don't have that context (multiple supported versions, slow deploys, formal release gates), you're paying the complexity tax without the benefit. Start with GitHub Flow. You can always add structure later if the situation demands it — but you'll rarely need to.