Branching & Merging
Feature branches, merge, and rebase strategies for Python services shipping pyproject.toml, lockfiles, and Alembic migrations together.
Search across all documentation pages
Feature branches, merge, and rebase strategies for Python services shipping pyproject.toml, lockfiles, and Alembic migrations together.
git checkout main && git pull --rebase origin main
git checkout -b feat/api-91-refunds
# work ...
git fetch origin && git rebase origin/main
git push -u origin feat/api-91-refunds
# open PR -> squash merge to main after CI greenWhen to reach for this:
mainmain before PR reviewrelease/x.y trains with Django/FastAPI apps# Feature branch lifecycle
git switch -c feat/worker-retries main
uv run pytest -q
git commit -am "feat(worker): retry smtp errors [WRK-12]"
git fetch origin
git rebase origin/main
# conflict in uv.lock -> regenerate lock after resolving pyproject
uv lock
git add pyproject.toml uv.lock
git rebase --continue
git push --force-with-lease origin feat/worker-retriesWhat this demonstrates:
mainmain.| Branch | Purpose |
|---|---|
main | Always shippable integration |
feat/* | Ticket work; rebased often |
release/x.y | Stabilization; fixes only |
hotfix/* | Production patch from tag |
# Cherry-pick migration fix to release branch
git switch release/2.3
git cherry-pick abc1234 # commit with Alembic revision
uv run alembic upgrade head
uv run pytest -qmain daily.main into release/* - Pulls unvetted features. Fix: cherry-pick only.| Alternative | Use When | Don't Use When |
|---|---|---|
| Trunk-based + flags | Mature CI and feature flags | Long release trains with schema migrations |
GitFlow develop | Legacy org mandate | Team prefers trunk + release/* |
| Merge commit on PR | Preserve PR boundary metadata | History noise is a concern |
| Rebase merge | Linear history with PR grouping | Policy forbids any rewrite |
Squash for feature PRs on main; merge commit when preserving multi-commit feature narrative is required.
Accept one side's pyproject.toml, run uv lock, stage regenerated lock - never hand-merge lock JSON.
Target 1-3 days; if longer, split ticket or integrate behind feature flag.
Yes - enable auto-delete on GitHub; local git branch -d after merge.
Coordinate Alembic revision chain - second PR bases on first until first merges.
Require PR, ruff, pytest, reviews - no direct push except break-glass role.
Same rules per service folder; path filters in CI run only affected uv projects.
Cherry-pick to main and active release/*; tag patch after staging validation.
Merge dependabot PRs as-is or rebase via GitHub button - keep lockfile consistent with uv sync --frozen CI.
See Git for Data/Notebooks - nbstripout reduces noise.
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+.
Reviewed by Chris St. John·Last updated Jul 16, 2026