FAQ & troubleshooting

Is it safe? Will it delete work?

Nothing is ever deleted automatically. prune always asks first (grouped by risk), and only branches the analyzer can prove dead are offered: ancestor-merged, or content-merged (the branch's final tree exists in a base branch's history — the squash/rebase fingerprint). Unmerged work is only ever flagged as stale, never deleted, unless you opt in with an explicit force rule (rules: [{ match, mode: "any" }]) — and even then it's local-only and still confirmed. Before any deletion that loses unique commits, the refs are written into a git bundle; git-cleanup backup restore (or one git fetch) brings them back.

Why does git branch --merged miss so many branches?

Squash merges, rebase merges, and cherry-picks rewrite the commits, so the branch's SHAs vanish from the base's history. Ancestry checks can't see them. git-cleanup fingerprints the branch's final tree — if that tree appears in a base's history, the branch's content is already in the base, even though its commits aren't.

Could the content check be wrong?

It's deliberately conservative. A branch is only content-flagged when its tip tree exists in a base's history and differs from the tree at the branch's own starting point — so net-empty branches (fully reverted work, no-op commits) whose tree coincidentally matches an old base tree are never called merged. The golden-history test suite pins rebase, cherry-pick, octopus, and fast-forward scenarios, and the seeded differential fuzz compares verdicts against each branch's true fate on thousands of random histories.

PR tracking says nothing. What do I set?

git-cleanup doctor

One diagnostic report: git present? gh present? per-forge tokens set? remote detected? config loading? Each check comes with a fix hint. Missing tokens never break scans — the tool degrades to pure-Git detection.

Why does prune --remote refuse to delete my version branch?

Remote deletion is a separate opt-in step, and version-shaped names (v1, 5.x, release/*…) are protected by default. Maintenance branches are often merged by ancestry yet still owned upstream; protect them with a two-line glob if you point the tool at a shared remote.

My branch is squash-merged but still listed as stale

Content detection runs against the base branches the repo actually uses (from the remote's HEAD — main, master, develop, dev). If the work landed on a different branch, add it to the base detection or check with scan --verbose to see the reason per branch. A branch is also kept while it has an open PR or is below the age threshold.

It says "non-interactive session: pass --yes". I did pass --yes.

If you're seeing this from a shell hook, the snippet may set a different cwd or run before config is readable — run git-cleanup doctor and the exact failing command by hand. Note --force is an alias for --yes, and GIT_CLEANUP_YES=1 works too.

Does it need network access?

Merge detection is fully offline — it only reads the local object database. Network is used only for PR enrichment and report-issue, and only when a forge remote and token are available.

Can I use it in CI?

Yes — scan --check as a gate, sweep --yes --json in cron, and the scan-report GitHub Action for scheduled reports. The repo also ships a structurally-mirrored GitLab CI template. See Automation.