Branches are coordination artifacts, not permanent records. The durable history
is main, release tags, merged PRs, issues, docs, and validation receipts.
This policy keeps a fast-moving repository easier to audit without deleting active work or breaking contributor forks.
mainand protected release branches;- branches backing open pull requests;
- active maintainer branches with recent commits;
- long-lived integration branches that are documented in an issue or project;
- fork branches owned outside the organization.
Candidates for cleanup are branches that are all of:
- merged, abandoned, or superseded;
- not referenced by an open PR;
- older than the agreed stale window;
- not a release, support, or protected branch;
- not needed for a documented investigation.
Prefer closing or merging the PR first, then deleting the branch through GitHub. Do not bulk-delete remote branches without a dry-run list and maintainer review.
Use names that make ownership and purpose obvious:
| Purpose | Pattern |
|---|---|
| Maintainer feature/fix | fix/<short-topic> or feature/<short-topic> |
| Codex/automation work | codex/<short-topic> |
| Documentation | docs/<short-topic> |
| Release/support | release/<version> or support/<version> |
Avoid branch names that encode secrets, customer names, private hostnames, or local machine details.
Use the dry-run helper to list possible stale branches. It does not delete anything:
python ods/scripts/maintainers/list-stale-branches.py --days 45By default the helper excludes main, master, develop, public-beta,
release/*, support/*, and the default branch recorded by local origin/HEAD.
It also excludes branches backing open PRs when the GitHub CLI is available.
--include-open-prs only bypasses the PR filter; release/default exclusions
still apply. The helper does not query GitHub branch-protection rules.
Review the output before deleting anything. When in doubt, leave the branch and link it to an issue describing why it should stay.