graph TD
subgraph G0["Repo controls - Maintainer and Admin"]
G0A["Set roles and permissions<br/>Admin: merge to main<br/>Contributors: no direct push to main"] --> G0B["Protect main branch<br/>Require PRs<br/>Block force-push<br/>Restrict who can push"]
G0B --> G0C["Require reviews<br/>Minimum reviewers<br/>CODEOWNERS optional"]
G0C --> G0D["Require CI checks<br/>Tests, lint, build, security optional"]
G0D --> G0E["Define merge method<br/>Squash or merge-commit or rebase-merge"]
end
subgraph G1["Contributor workflow"]
C1["Pick a task or issue"] --> C2["Fetch updates<br/>git fetch origin"]
C2 --> C3["Create branch from main<br/>git switch -c feature/x origin/main"]
C3 --> C4["Make changes and commit locally"]
C4 --> C5["Run local checks<br/>tests, lint, build"]
C5 --> C6["Push branch<br/>git push -u origin feature/x"]
end
subgraph G2["Pull request workflow"]
P1["Open PR<br/>feature/x to main"] --> P2["CI runs on PR"]
P2 --> P3{"CI checks pass?"}
P3 -- "No" --> P3A["Fix on branch and push commits"] --> P2
P3 -- "Yes" --> P4["Review happens"]
P4 --> P5{"Approvals satisfied?"}
P5 -- "No" --> P5A["Revise on branch and push updates"] --> P4
P5 -- "Yes" --> P6["Admin merges PR<br/>per merge policy"]
end
subgraph G3["After merge to main"]
M1["main updated"] --> D1["CI runs on main"]
D1 --> D2["Deploy to staging optional"]
D2 --> D3{"Deploy to production?"}
D3 -- "Approval required" --> D4["Manual approval gate optional"] --> D5["Deploy to production"]
D3 -- "Automatic" --> D5
D5 --> D6["Tag release and publish notes optional"]
D6 --> D7["Monitor and alerting"]
end
subgraph G4["Common exceptions and recovery"]
E1["Push rejected: remote ahead<br/>non-fast-forward"] --> E2["Update your branch<br/>git fetch then rebase or merge from origin/main"] --> P1
E3["Bad change merged"] --> E4["Revert via PR<br/>git revert then PR then merge"] --> M1
E5["Urgent fix needed"] --> E6["Create hotfix branch from main or tag<br/>hotfix/x"] --> P1
end
G0E --> C1
C6 --> P1
P6 --> M1
- Create a branch from
origin/mainbefore coding (feature/<short-name>). - Commit small, focused changes with clear messages.
- Run tests/lint/build locally before pushing.
- Push only to your branch, then open a PR into
main. - Respond to CI failures and review feedback by pushing additional commits to the same PR.
- Keep your branch current with
origin/main(rebase/merge) if the PR gets stale. - Use PR descriptions: what changed, why, how to test, risks/rollout notes.
- Don’t push directly to
main(ever). - Don’t force-push to shared branches (especially
main). - Don’t merge your own PR (unless explicitly allowed).
- Don’t bypass CI or merge while required checks are failing.
- Don’t “fix” a rejected push by overwriting remote history (avoid
git push --force). - Don’t mix unrelated changes in one PR (split PRs by purpose).
- Enable branch protection on
main(PR-only, block force-push). - Require CI checks and at least one approval before merge.
- Use CODEOWNERS for sensitive areas (infra, deployment, security).
- Choose and enforce a merge method (squash recommended for simplicity).
- Use environment approvals for production deployments (optional but recommended).
- Revert via PR if a bad change lands (avoid rewriting history).
- Don’t disable protections “just to get it through.”
- Don’t merge with failing checks unless it’s a deliberate emergency exception with documentation.
- Don’t allow “direct-to-main” pushes for routine work.
| Term | Meaning |
|---|---|
| Admin / Maintainer | Person who configures repo settings and merges to protected branches (like main). |
| Contributor | Developer who pushes to feature branches and submits pull requests; typically cannot push to main. |
main |
Default integration branch; shared source of truth. |
| Branch protection | GitHub rules enforcing workflow (PR-only merges, block force-push, required reviews/checks). |
| Pull request (PR) | Proposal to merge a branch into main with review discussion and automated checks. |
| Review | Human feedback on a PR (comment, request changes, approve). |
| Approval | Formal “OK to merge” on a PR, often required by protection rules. |
| CODEOWNERS | Path-based required reviewers (e.g., /infra/* requires DevOps approval). |
| CI (Continuous Integration) | Automated validation (tests/lint/build/scans) run on PRs and/or main. |
| Status checks | CI results surfaced to GitHub (pass/fail); can be required to merge. |
| Merge method | How GitHub integrates PR changes (squash merge, merge commit, rebase-merge). |
| Squash merge | Combines PR commits into one commit on main. |
| Merge commit | Preserves branch history via a merge commit on main. |
| Rebase-merge | Replays commits onto main for a linear history (no merge commit). |
| Non-fast-forward | Push is rejected because the remote branch has commits you don’t have locally (“fetch first”). |
| Rebase | Updates your branch by replaying your commits on top of the latest origin/main. |
| Conflict | Git can’t automatically combine changes; requires manual resolution. |
| Revert | A new commit that undoes a previous commit (history-preserving rollback). |
| Hotfix | Urgent fix branch from main (or a release tag) merged via PR with expedited review. |
| CD (Delivery/Deployment) | Automated deploy pipeline after merge; often staging auto and production gated. |
| Environment approval gate | Manual approval required to deploy to protected environments (e.g., Production). |
| Release tag | Version marker pointing to a specific commit (e.g., v1.2.3). |
| Artifact | Build output (image/package/binary) produced by CI that is deployed. |
| Monitoring / Observability | Metrics/logs/traces/alerts used to verify health after deployment. |