balai is French for broom. git-balai deletes local branches whose changes
have already landed in the remote's primary branch.
go install fcuny.net/git-balai@latestWith the binary on your PATH, it can also be run as git balai.
git balai # delete merged branches
git balai -dry-run # only show what would be deleted
git balai -worktrees # also remove worktrees of merged branches
git balai -version # print the versionIt runs in the current repository and:
- Refuses to run if there are staged or unstaged changes to tracked files.
- Picks the remote: the first of
origin,githuborworkthat exists, or the only remote if there is just one. - Asks the remote which branch its
HEADpoints to (the primary branch) and fetches it, so a stale local primary branch doesn't hide merged branches. - Deletes every local branch whose changes are in the remote primary branch:
- merged: the branch is an ancestor of the primary branch;
- rebased: every commit has an equivalent commit (same patch) upstream;
- squashed: the branch's combined changes match a single upstream commit.
It never deletes the primary branch, or the branch checked out in the current
or the main worktree. Each deleted branch is logged with its commit, so it can
be restored with git branch <name> <commit>.
A merged branch checked out in a linked worktree is kept, unless -worktrees
is given. Then the worktree is removed with git worktree remove and the
branch is deleted, but only if the worktree is not locked and has no modified
or untracked files. Ignored files (build output, .env, ...) don't count as
changes and are removed with the worktree, so check with -dry-run first.
A worktree whose directory was already deleted is pruned without -worktrees.
A squash merge whose conflicts were resolved differently from the branch, or that was edited before landing, won't match and the branch is kept.
make # lint, test and build into bin/
make test
make lintBSD 3-Clause, see LICENSE.