GitFlow Commit Graph
Main (cyan), develop (blue), feature (yellow), hotfix (pink). Press New Feature to fork a feature branch with two commits. Press Merge to Main to animate the merge commit flowing back.
Code example
GitFlow branch commands and a feature flags pattern for trunk-based development.
# GitFlow branch lifecycle
# Start a new feature from develop
git checkout develop
git pull origin develop
git checkout -b feature/user-authentication
# Work and commit on the feature branch
git add auth.js
git commit -m "add JWT token validation"
git add middleware.js
git commit -m "add auth middleware to protected routes"
# Open a PR to develop (review, CI runs)
gh pr create --base develop --title "Add user authentication"
# After approval — squash merge to keep history clean
git checkout develop
git merge --squash feature/user-authentication
git commit -m "feat: add user authentication (#42)"
git branch -d feature/user-authentication
# Release: develop ? release branch ? main + tag
git checkout -b release/v2.1.0
# QA testing... bump version, fix bugs...
git checkout main
git merge --no-ff release/v2.1.0
git tag -a v2.1.0 -m "Release v2.1.0"
git push origin main --tags
# Emergency hotfix directly from main
git checkout -b hotfix/xss-patch main
git commit -am "fix: sanitize user input in comment renderer"
git checkout main
git merge --no-ff hotfix/xss-patch
git checkout develop
git merge --no-ff hotfix/xss-patch
// Feature flags — the trunk-based alternative to long-lived branches
// Commit directly to main, hide in-progress work behind a flag
const flags = {
newCheckout: process.env.FF_NEW_CHECKOUT === 'true',
aiRecommendations: process.env.FF_AI_REC === 'true',
darkMode: true,
};
// In your route/component
app.get('/checkout', (req, res) => {
if (flags.newCheckout) {
return newCheckoutHandler(req, res);
}
return legacyCheckoutHandler(req, res);
});
// Production: deploy to 1% of users first
function isEnabled(flag, userId) {
const bucket = userId % 100;
return flag.rollout > bucket;
}
// Trunk-based workflow
# Every developer pushes to main (or a short-lived branch < 1 day)
# CI must be fast (< 5 min) — every push must stay green
# Feature flags gate incomplete work from users
# No long-lived branches ? no merge conflicts
git checkout main
git pull origin main
git add .
git commit -m "feat: add cart count badge [behind FF_CART_BADGE]"
git push origin main # triggers CI ? auto-deploy to staging
Key concepts
GitFlow
Five branch types with strict rules. Features branch from develop, releases branch from develop to main, hotfixes branch from main. Good for versioned releases. Bad for continuous deployment — too slow, too many merges.
Trunk-Based Development
Everyone commits to main daily. Feature flags hide incomplete work. CI gates every push. Used by Google, Meta, and most CD teams — but requires fast CI and high test coverage to stay stable.
Pull Request
A PR is a proposal to merge one branch into another. It triggers CI, opens a review window, documents the "why" in comments, and creates an audit trail. Merge strategies: merge commit, squash, or rebase.
Hotfix
A hotfix branches directly from the production tag (or main), fixes the critical bug, gets deployed, then merges back to both main and develop. Never block a hotfix behind a slow release process.