2.6 KiB
Local branch cleanup
MIT licensed. See LICENSE.wanjakrah and ATTRIBUTION.md.
Requires Git, JDK 25 on PATH, and a Unix-like system with env -S.
Run from the repository you want to clean (including any subdirectory):
./git-tools/pruneLocalBranches --check
./git-tools/pruneLocalBranches -d feature/example
./git-tools/pruneLocalBranches -d '*'
./git-tools/pruneLocalBranches --help
From another repository, use the absolute path to this script. Its location does
not select the repository; the current working directory does. Always quote '*'.
Alternatively launch with java --source 25 /path/to/pruneLocalBranches ....
The script fetches all origin branches and prunes stale local origin tracking references. A failed fetch stops the operation. It never pushes, deletes remote branches, removes folders, or changes working files.
A local branch is eligible only when no same-name branch exists on origin, it is
not checked out in any worktree, and all its commits are reachable from the current
HEAD or local main. Configured upstream names do not affect this decision:
S6-deployment tracking origin/main is not protected by that mapping. If local
main is missing, only HEAD counts. Neither local branch is updated by fetching.
Squash/rebase merges can leave different commit identities, so these branches may
be refused even when their changes were merged. The refusal lists the commits.
Checked-out branches are always refused, protecting their uncommitted work too.
--check prints eligibility and protection reasons. Deletion prints the candidates
and requires exactly DELETE; any other response or end of input cancels. Bulk
deletion skips protected branches and reports why. Before each deletion the script
rechecks eligibility and verifies that the branch still points to the displayed
commit. Avoid concurrent Git operations while running it; bulk deletion is not
atomic, so an error can leave earlier candidates already deleted.
Implementation: a Java 25 compact source file runs Git through ProcessBuilder
without a shell. After the explicit safety checks, git branch -D removes the local
ref, bypassing Git's separate upstream-based merge check. No build or dependencies
are needed. Exit codes: 0 success or cancellation, 1 error/blocked deletion,
2 invalid arguments.
Run the isolated integration checks with
python3 git-tools/test-prune-local-branches.py. They create temporary repositories
under the system temporary directory, print their location for inspection, and
exercise single/bulk deletion, protection rules, cancellation and fetch failures.