Git Best Practices
A condensed summary of the 25 most important Git practices for Python teams - clean history, reviewable commits, and CI-aligned hooks.
-
mainis always integration truth: Every merged PR passesruff,pytest, and typecheck; never leavemainbroken overnight (Essential Git Commands). -
Commit the lockfile:
uv.lock(orpoetry.lock) required for reproducibleuv sync --frozenin CI - never gitignore it. -
Ticket IDs in every commit:
feat(billing): tax line [BILL-42]- cherry-picks torelease/*depend on traceable messages. -
Squash merge features to
main: One ticket, one commit on integration branch when team policy allows. -
Short-lived feature branches: Target 1-3 days; rebase
maindaily to avoid lockfile and Alembic conflicts. -
Cut
release/x.yfor coordinated trains: API + worker + migration ship together; new features land onmainuntil tag. -
Release branch accepts bugfixes only: Enforce with branch protection during freeze windows.
-
Cherry-pick to
release/*, never mergemainintorelease/*: Merging pulls unvetted features into the release candidate. -
Tag from
release/*after staging sign-off:v2.6.0triggers release pipeline; tag message lists deployables. -
Merge
release/*back tomainafter rollout: Preserve train boundary; delete release branch when complete. -
Hotfix branches from production tags:
git checkout -b hotfix/2.5.1 v2.5.0- not frommainwhen it is ahead of production. -
Backport every hotfix: Cherry-pick fix SHA to
mainand openrelease/*if still active. -
Never force-push shared branches:
main,release/*,hotfix/*history is audit evidence. -
pre-commit mirrors CI:
ruff check,ruff format, quickpytest- same commands as GitHub Actions (Git Configuration). -
PR template requires migration note: Alembic revisions need rollback plan or expand-contract strategy.
-
Branch protection requires status checks: Policy beats honor system for required workflows.
-
Never commit
.envor secrets:.env.exampleonly; production via platform secret inject. -
Do not commit
.venv/,__pycache__/, ordist/: Artifacts belong in CI/CD, not git. -
Conventional commits for changelog automation: Pair with semantic-release or custom changelog script if adopted.
-
Tag creation restricted: Tags trigger production - rulesets or release manager role.
-
Monorepo: document tag strategy: One monorepo tag vs per-service tags - pick one and document.
-
API + worker schema changes linked: Event contract drift breaks async flows - one PR or explicitly linked PRs.
-
Review lockfile diffs on dependency PRs: Unexpected new transitive deps are supply-chain red flags.
-
Document rollback in release notes: Image digests, migration down plan, feature flag kill switch.
-
Interactive rebase on private
feat/*only:--force-with-leasebefore PR review; never on shared branches.
FAQs
GitFlow develop branch or trunk + release?
Most Python service teams use trunk + release/hotfix - simpler than long-lived develop unless org mandates GitFlow.
How strict on commit message format?
Enforce ticket id and imperative mood; conventional type scope when changelog automation depends on it.
Dependabot PR merge policy?
Auto-merge patch bumps when CI green; minor/major needs human review of lockfile diff.
Notebooks in git?
Follow Git for Data/Notebooks - nbstripout mandatory.
Related
- Branching & Merging - strategies
- Merge Conflict Resolution Checklist - conflict process
- GitHub CLI - PR automation
- CI/CD Pipelines - workflow gates
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.