Branching Strategy & Workflow Guide
A modern, high-velocity approach to version control designed for teams shipping continuously. Balances stability, speed, and code quality.
Overview & Philosophy
Traditional GitFlow is overkill for most modern development teams. It introduces long-lived integration branches, increases merge conflicts, and slows down deployment cycles. At .git, we advocate for a Trunk-Based Development model with short-lived feature branches.
This strategy minimizes integration pain, enables continuous deployment, and keeps the main branch always in a releasable state. Combined with automated CI/CD pipelines, it reduces cognitive overhead and accelerates feedback loops.
Core Principles
1. Main branch is always deployable.
2. Short-lived branches (1-3 days max).
3. Automated checks gate every merge.
4. Small, frequent PRs over massive batch changes.
Recommended Branch Model
Our default workflow centers around a single stable integration branch (main) with ephemeral feature branches branching off and quickly merging back.
When to Deviate
Use release/vX.Y.Z only for coordinated production releases requiring hotfix isolation. Use hotfix/ for critical production patches that must bypass standard PR workflows.
Branch Naming Conventions
Consistent naming enables automation, clearer auditing, and easier pipeline routing. All branches should follow the format:
type/descriptive-slug
| Type | Prefix | Example | Usage |
|---|---|---|---|
| Feature | feature/ | feature/user-auth | New functionality or enhancements |
| Fix | fix/ | fix/login-timeout | Bug fixes (non-critical) |
| Hotfix | hotfix/ | hotfix/ssl-cert-expiry | Critical production patches |
| Chore | chore/ | chore/update-deps | Dependencies, config, CI updates |
| Docs | docs/ | docs/api-endpoints | Documentation changes only |
| Refactor | refactor/ | refactor/db-queries | Code restructuring without behavior change |
Step-by-Step Workflow
- Sync: Always start from a fresh
main. Pull latest changes before branching. - Create: Check out a new branch using the naming convention.
- Develop: Work in small logical commits. Keep WIP local unless sharing is necessary.
- Push & Create PR: Push to remote and open a Pull Request immediately. Enable draft status if incomplete.
- Automate: CI pipeline runs linting, tests, security scans, and builds previews.
- Review: At least one approving review required. Resolve all comments and checks.
- Deploy: Trigger canary/staging deployment automatically.
- Merge: Squash & merge into
main. Auto-delete source branch. - Release:
mainauto-deploys to production (or tagged release).
git checkout -b feature/new-search
# ... commit changes ...
git push -u origin feature/new-search
✓ Pull Request created: https://.git.dev/pr/42
Automation & CI/CD Integration
Manual enforcement fails at scale. Configure branch protection and pipeline gates in your .git dashboard:
- Branch Protection: Require pull request reviews, status checks, and linear history (squash/merge only).
- Auto-Merge: Enable auto-merge when all checks pass and approvals are met.
- Preview Environments: Spin up isolated staging URLs per PR using our infrastructure hooks.
- Conventional Commits: Enforce
feat:`, `fix:`, `chore:` prefixes to auto-generate changelogs and semver tags.
Example Pipeline Config
on:
pull_request:
branches: [ main ]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run lint
- run: npm test
- uses: .git/deploy-preview@v2
with:
env: staging
auto-destroy: true
Best Practices
- Keep PRs small: Aim for <400 lines changed. Larger PRs should be split into logical chunks.
- Sync frequently: Rebase or merge
maininto your feature branch daily to avoid massive conflict resolution. - Document in PR: Include screenshots, test steps, and migration notes. Link to issue/ticket.
- Never force push to shared branches: Only
mainandrelease/*are strictly protected. Feature branches can be rewritten, but communicate with your team. - Delete after merge: Keep repository history clean. .git automatically suggests branch cleanup.
Anti-Patterns to Avoid
🚫 Long-Lived Branches
Branches older than 5 days accumulate drift, cause painful merges, and hide breaking changes. If a feature takes longer, break it into smaller deliverables or use feature flags.
🚫 Direct Commits to main
Bypassing PRs eliminates review gates and automated checks. Only emergency hotfixes should temporarily bypass this, and must be post-reviewed within 24h.
🚫 "Works on My Machine" Deploys
Always verify pipeline artifacts and staging environments before marking PRs as ready. Local success ≠ production readiness.
Frequently Asked Questions
What about microservices?
Each service repository follows this same strategy. Shared libraries should be versioned separately and consumed via package managers to avoid tightly coupled mono-repo branching.
Can we use develop branch?
We don't recommend it for most teams. It adds a second integration point that doubles review overhead. If your team requires it, configure develop with the same protection rules as main.
How do we handle breaking changes?
Use semantic versioning. Tag breaking changes explicitly in PR titles (feat!:) and ensure CI blocks merges to stable channels until major version bumps are approved.