Prerequisites
- Git installed locally
- Basic git add/commit/push/pull experience
What You'll Learn
- Describe Git Flow's branch roles: main, develop, feature/*, release/*, hotfix/*
- Describe trunk-based development: short-lived branches merged to main behind feature flags
- Choose the right model based on release cadence, team size, and CI/CD maturity
- Perform an interactive rebase to clean up a feature branch before merging
Theory
A branching strategy is really a policy for two things: how long a branch lives before merging, and what state main is allowed to be in at any moment. The two dominant models answer both questions almost oppositely.
Git Flow
Git Flow defines fixed branch roles: main always reflects production, develop is the integration branch for the next release, feature/* branches off develop and merges back into it, release/* branches off develop when preparing a release (only bugfixes land here), and hotfix/* branches directly off main for urgent production fixes, merging into both main and develop. It suits products with a scheduled, versioned release cadence.
Trunk-based development
Trunk-based development keeps a single long-lived branch (main/trunk), with feature branches living hours to a couple of days at most before merging back, gated by CI. Work that isn't ready to ship is hidden behind a feature flag rather than kept on a long-lived branch — decoupling "merged" from "released". It suits teams with strong CI/CD and frequent (daily or faster) deployment.
Architecture
Git Flow: feature branches integrate via develop, release branches stabilize, hotfixes patch main directly and flow back down
Hands-On Lab
Clean up a messy feature branch with interactive rebase before opening a PR:
git checkout feature/login-form
git log --oneline main..HEAD # see exactly which commits are yours
git rebase -i main
# In the editor, mark commits: pick the first, 'squash' (or 's') the
# "fix typo" / "wip" commits into it, reword the final message
# If main has moved on since you branched, rebase onto the latest first:
git fetch origin
git rebase origin/main
# Force-push required after any rebase (history was rewritten) —
# --force-with-lease refuses if someone else pushed to the branch meanwhile
git push --force-with-lease origin feature/login-formBest Practices
Match the model to your deployment pipeline, not the other way around
If you deploy on every merge to main, Git Flow's develop/release branches add process without benefit — trunk-based is the natural fit. If you ship versioned releases on a schedule, Git Flow's structure genuinely earns its complexity.Use --force-with-lease, never --force
--force-with-leaserefuses to overwrite a branch if someone else pushed to it since you last fetched, preventing you from silently discarding a teammate's work.Common Mistakes
Long-lived feature branches under a trunk-based label
Calling a branch 'trunk-based' while letting it live for three weeks defeats the entire point — the value comes from small, frequent merges that keep integration conflicts small and CI feedback fast.Rebasing a shared branch other people have already pulled
Rebasing rewrites commit hashes — anyone who already pulled the old version now has a diverged, conflicting history. Only rebase branches that are exclusively yours (or where the whole team has explicitly agreed to the rewrite).Troubleshooting
Rebase stops with a conflict: git pauses and shows which files conflict — edit them to resolve, then git add the resolved files and git rebase --continue. If it gets too tangled, git rebase --abort returns you to the exact state before the rebase started, with nothing lost.
Force-pushed and now the branch looks broken: git reflog records every position HEAD has been at locally, including before a bad rebase or reset — find the commit hash from before the mistake and git reset --hard <that-sha>to recover it, as long as it hasn't been garbage-collected (reflog entries expire, default 90 days).
Cheat Sheet
Branching & Merging
git checkout -b feature/xCreate and switch to a new branchgit switch -c feature/xModern equivalent of checkout -bgit merge feature/xMerge a branch into the current branchgit branch -d feature/xDelete a branch that's been mergedgit branch -D feature/xForce-delete a branch, merged or notgit branch -vvList branches with their upstream tracking statusFrequently Asked Questions
Summary
Git Flow's fixed branch roles suit scheduled, versioned releases; trunk-based development's short-lived branches and feature flags suit frequent, CI-driven deployment. Pick based on your actual release cadence and CI/CD maturity — and remember interactive rebase and reflog are the tools that make cleaning up (and recovering from) either model safe.