Git & deployment workflow
Best practices for branching, GitHub protection, CI/CD, releases, and hotfixes. Use this as the team standard so environments stay predictable and code doesn’t drift.
1. Define a source of truth
Choose and document what each long-lived branch represents:
| Branch | Role |
|---|---|
main | Production truth — what is (or will be) live in production |
staging | Pre-production truth — final verification before production |
develop | Latest integrated work — daily integration target for features |
Everyone should agree: no “mystery” branches as the canonical state for an environment.
2. Protect the important branches
In GitHub (branch protection rules), for main, staging, and develop:
- Protect the branches (no accidental force-push or delete)
- Require pull requests — no direct commits to these branches
- Require approvals — at least 1–2 reviewers before merge
- Block direct pushes to protected branches
- Require passing CI — merges only when pipelines are green
- Optional: require linear history or squash merges for a clean, reviewable history
This keeps production-oriented branches stable and auditable.
3. Tie deployments to branches only
CI/CD should be deterministic: each environment maps to one branch, not ad-hoc picks.
| Branch event | Typical deployment target |
|---|---|
Push / merge to develop | Development environment |
Push / merge to staging | Staging environment |
Push / merge to main | Production |
Avoid routine releases via “deploy this random branch” — that breaks traceability and repeatability. Exceptions should be rare and documented (e.g. emergencies with a follow-up process).
4. Tag every production release
Every production deployment should create a Git tag, for example:
v1.7.0v1.7.1
Tags should point to the exact commit that was deployed. That way you always know what code is live, can diff releases, and can roll back or audit incidents precisely.
5. Hotfix policy
Sometimes a production hotfix is unavoidable. That’s fine — but follow a strict flow so staging and develop don’t fall behind.
Rules
Hotfix branches start from
main- Branch: e.g.
hotfix/v1.7.2-critical-fixfrom currentmain.
- Branch: e.g.
Fix, review, merge to
main, deploy production- Use your normal protected-
mainflow (PR + CI + approvals).
- Use your normal protected-
After deployment, merge the hotfix back into:
stagingdevelop
This is back-merging / forward-porting (depending on direction): the same fix must flow into all integration lines. Without this, branches drift and the next regular release can re-introduce bugs or lose fixes.
Summary diagram (conceptual)
main ──●── hotfix merge ──●── (prod tag v1.7.2)
\ /
hotfix ●──●──●────────┘
\
staging ───────────●── merge hotfix
develop ───────────●── merge hotfixQuick checklist
- [ ]
main/staging/developmeanings documented - [ ] Branch protection on all three
- [ ] CI required on merge
- [ ] Deploy only from mapped branches for normal releases
- [ ] Production tags on every prod deploy
- [ ] Hotfixes from
main, then merged intostaginganddevelop
Related
- Environments — Fangate URLs (production, development, staging)
- Developer onboarding — local setup and flows