Manage Spork Branches
How to create, maintain, and reason about feature branches on a sporked repository. See create-a-spork for initial setup.
Branch types
Upstreamable features (feature/upstream/*)
Changes intended to be contributed upstream. Branch off main so the diff is clean — no local tooling or workflows mixed in.
cd ~/code/3rd/kingfisher
git fetch origin
git checkout -b feature/upstream/forgejo-support origin/main
# Make changes, commit as normal
git push -u origin feature/upstream/forgejo-supportThe mirror-sync workflow will automatically rebase this branch onto main each day.
To see what the upstream contribution looks like:
git log main..feature/upstream/forgejo-support --oneline
git diff main...feature/upstream/forgejo-supportTo create a preview PR on forge (targets the mirror, not upstream):
# From the eblume/<project> repo, PR targeting mirrors/<project>:main
# This gives a public URL showing the diff without filing upstream
tea pr create --repo mirrors/kingfisher --head eblume/kingfisher:feature/upstream/forgejo-support --base mainWhen ready to contribute upstream, manually translate the branch to a GitHub PR.
Non-upstreamable features (feature/local/*)
Local-only changes that will never go upstream. Branch off blumeops so you have access to all local tooling.
cd ~/code/3rd/kingfisher
git fetch origin
git checkout -b feature/local/custom-rules origin/blumeops
# Make changes, commit as normal
git push -u origin feature/local/custom-rulesThe mirror-sync workflow will automatically rebase this branch onto blumeops each day.
The deploy branch
The deploy branch is a build artifact — rebuilt fresh by mirror-sync daily. It contains everything merged together: blumeops + all feature/local/* + all feature/upstream/*. Use this branch for deployments (e.g., ArgoCD targetRevision).
Never commit to or work from deploy.
Working with rebasing branches
Because mirror-sync force-pushes rebased branches daily, local checkouts will diverge. Always pull with rebase:
git pull --rebase origin feature/upstream/my-changeOr set it as default for the repo:
git config pull.rebase trueThis is the fundamental trade-off of the spork strategy: small frequent rebases instead of rare catastrophic merges.
When rebases fail
If upstream changes conflict with a feature branch, mirror-sync will skip that branch and log an error. Recovery:
cd ~/code/3rd/kingfisher
git fetch origin
git checkout feature/upstream/my-change
git rebase origin/main
# Resolve conflicts...
git push --force-with-lease origin feature/upstream/my-changeThe next mirror-sync run will pick up the resolved branch and rebuild deploy.
TODO: Workflow failures — whether from rebase conflicts or upstream history rewrites (force-push on main) — are currently only visible in the Forgejo Actions UI. Alerting via Grafana is planned but not yet implemented.
Future: .spork.toml
For repos with multiple feature branches, a .spork.toml file on the blumeops branch could declare:
- Branch dependencies (stacked branches —
bardepends onfoo) - Feature descriptions (what the branch is for, in prose)
- Upstream/local classification (as an alternative to the naming convention)
This is not yet implemented. For now, the feature/upstream/* vs feature/local/* naming convention is the source of truth.
See also
- create-a-spork — initial setup
- manage-forgejo-mirrors — mirror setup and PAT rotation