Files

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.