Suggest an editImprove this articleRefine the answer for “Git branching strategies (Git Flow, GitHub Flow)?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Git branching strategies** define how a team structures branches for releases. Git Flow uses main, develop, feature/*, release/*, and hotfix/* branches for scheduled versioned releases. GitHub Flow uses only main and short-lived feature branches, merging directly to main for continuous deployment. **Key rule:** versioned releases need Git Flow; daily deploys need GitHub Flow.Shown above the full answer for quick recall.Answer (EN)Image**Git branching strategies** define structured rules for how a team creates, merges, and deletes branches to coordinate development without breaking production. ## Theory ### TL;DR - Git Flow: factory assembly line with dedicated stations for features, testing, and fixes. GitHub Flow: food truck that cooks and serves immediately. - Core split: Git Flow keeps a long-lived `develop` branch as the integration point before production. GitHub Flow has no `develop` and merges directly to `main`. - Scheduled versioned releases (desktop app, game)? Git Flow. Continuous web deploys? GitHub Flow. - Team of 10+ with quarterly releases: Git Flow. Team of 1-10 shipping daily: GitHub Flow. ### Quick example ```bash # GitHub Flow: one short cycle, main stays deployable git checkout main git pull origin main # always start from latest git checkout -b feature/user-login # short-lived branch git add . && git commit -m "Add login form" git push origin feature/user-login # open PR, review, merge to main, delete branch git branch -d feature/user-login # main is deployable right now ``` One branch. One PR. Main receives the change and is ready to deploy the same day. ### Key difference Git Flow keeps a `develop` branch as the permanent integration point. Features land on `develop` first. Then a `release/*` branch stages production-ready code. Only after that does `main` get a versioned tag like v1.2. GitHub Flow removes `develop` entirely: branch from `main`, open a pull request, merge back to `main` when approved. That is the whole structural difference. Git Flow is heavier but predictable for teams with fixed release schedules. GitHub Flow is faster for teams that deploy after every review. ### When to use - Mobile or desktop apps with quarterly releases: Git Flow handles versioning cleanly. - Web apps or SaaS with daily deploys: GitHub Flow cuts branch overhead. - Solo devs or small teams (1-5 people): GitHub Flow, no workflow tax. - Enterprise with compliance audits: Git Flow gives a clean separation between production and staging. - Monorepos with microservices: GitHub Flow plus tags and selective CI jobs per service. ### Comparison table | Aspect | Git Flow | GitHub Flow | |---|---|---| | Branches | main, develop, feature/*, release/*, hotfix/* | main, feature/* (short-lived) | | Release cycle | Scheduled (v1.2 via release branch) | Continuous (merge to main = deploy) | | Team size | Medium-large (10+ devs) | Small-agile (1-10 devs) | | Tooling | git-flow extensions recommended | GitHub PRs + CI/CD | | Merge frequency | Low (features collect in develop first) | High (daily PRs to main) | | Best for | Electron, games, Chrome extensions | Next.js on Vercel, VS Code open-source | ### How git handles branches internally Git stores each branch as a lightweight pointer to a commit (a SHA-1 hash). Creating `feature/login` is just writing a small file under `.git/refs/heads/`. No code is copied. Merging finds the common ancestor via `git merge-base` and applies diffs from that point, either as a fast-forward or a merge commit. Git Flow adds CLI scripts (`git flow feature start`) that automate creation from `develop`. GitHub Flow skips those scripts and uses GitHub's pull request engine, which runs a server-side three-way merge. The first time I ran a hotfix through full Git Flow, the auto-backport to `develop` saved a fix that would otherwise have been lost in the next release cycle. That said, most web teams since then use GitHub Flow and solve the same edge case with feature flags. ### Common mistakes **Merging a feature directly to main in Git Flow** ```bash git checkout feature/add-api # branched from develop git checkout main git merge feature/add-api # skips develop, breaks integration ``` `develop` exists to catch integration bugs before they touch `main`. Skipping it breaks the whole model. Fix: use `git flow feature finish add-api`, which merges to `develop` automatically. **Keeping feature branches alive too long in GitHub Flow** ```bash git checkout -b feature/epic # created three weeks ago git merge main # merge conflict explosion ``` GitHub Flow requires short branches (1-3 days). If a feature takes weeks, split it into smaller PRs or use feature flags to hide incomplete work. Fix: `git rebase main` daily to stay current. **Skipping `--no-ff` on hotfix and release merges in Git Flow** ```bash git merge release/v1.0 # fast-forward erases the release step from history ``` Without `--no-ff`, history looks linear and you lose the audit trail showing when a release was merged. Fix: `git merge --no-ff release/v1.0`. **Not deleting merged branches** Dead branches accumulate fast. A repo can hit thousands of stale refs after a year. Fix: enable auto-delete in GitHub PR settings and run `git remote prune origin` periodically. ### Real-world usage - React: GitHub Flow. Features branch from main, PRs with CI checks. - VS Code: GitHub Flow. Daily main deploys to the Insiders build. - Linux kernel: Git Flow variant. `mainline` acts as develop, `stable/*` as release branches. - Electron: Git Flow for tagged releases like v25.0.0. - Kubernetes: trunk-based development (branches live less than a day). ### Follow-up questions **Q:** Walk through creating a hotfix in Git Flow. **A:** Branch from `main` with `git flow hotfix start fix-crash`. Commit the fix. Run `git flow hotfix finish fix-crash`. This auto-merges to both `main` (tagged v1.2.1) and `develop`, so the fix is not lost in the next release cycle. **Q:** Why not always use GitHub Flow? **A:** It lacks a staging buffer for bigger releases. Without `develop`, a bad merge can break `main` before CI catches it. Git Flow gives you a place to catch integration bugs before they reach production. **Q:** How do you handle versioned releases in GitHub Flow? **A:** Merge to `main` and create a git tag (v1.2) immediately. CI/CD picks up the tag and deploys that commit. Semantic versioning still applies, you just skip the dedicated release branch. **Q:** What is GitLab Flow and how does it differ? **A:** GitLab Flow adds environment branches like `staging` and `production` between feature branches and main. Git Flow uses release branches tied to version numbers instead. Different mental model, similar goal. **Q:** (Senior) In a monorepo with 50 services, how does GitHub Flow scale without breaking deploys? **A:** Path filters in CI config (e.g., `changed-files: ['services/auth/**']`) trigger only the relevant jobs. Canary deploys and feature flags let you merge incomplete code without affecting users. Each service gets its own version tag. ## Examples ### Creating and merging a feature branch (GitHub Flow) ```bash git checkout main git pull origin main git checkout -b feature/use-auth-hook # src/hooks/useAuth.js # export const useAuth = () => { ... checks token in localStorage ... } git add src/hooks/useAuth.js git commit -m "Add useAuth hook with token check" git push origin feature/use-auth-hook # open PR on GitHub, 2 reviewers approve # auto-merge to main, CI runs tests green # Vercel picks up main and deploys git branch -d feature/use-auth-hook ``` PR opened, reviewed, merged, deployed the same day. Main never had an unstable state. ### Git Flow hotfix with backport to develop ```bash # Production crash discovered during release/v1.2 prep git checkout main git checkout -b hotfix/critical-crash # branch from main, not develop # fix the crash git add . && git commit -m "Fix null pointer in auth handler" git checkout main git merge --no-ff hotfix/critical-crash git tag -a v1.2.1 -m "Hotfix: null pointer in auth" git checkout develop git merge --no-ff hotfix/critical-crash # backport so fix lands in next release too git branch -d hotfix/critical-crash ``` `main` gets tagged v1.2.1 and deploys. `develop` also carries the fix, so the next scheduled release does not reintroduce the bug.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.