Git branch clean Function
A useful function for working with git is gbc, standing for Git Branch Clean.
It does the following
- Fetch remote-tracking branches and prune, so that branches deleted on the remote are deleted locally
- Get the list of local branches that are tracking remote branches and where the remote branch is "gone"
- Loop through the list and get the user to confirm deletion for each
This can be implemented as a shell function. Here are some implementations
Fish
Place the below in ~/.config/fish/functions/gbc.fish
function gbc
git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}')
while read --nchars 1 -l response --prompt-str="delete $branch (y/n)"
or return 1 # if read was aborted with ctrl-c/ctrl-d
switch $response
case y Y
echo Okay
set to_delete true
break
case n N
echo Not deleting
set to_delete false
break
case '*'
# we go through the while loop and ask again
echo Not valid input
continue
end
end
if $to_delete
git branch -D $branch
end
end
end
PowerShell
Add this to your profile file, which you can open with code $profile. I got Claude Chat to write this, but I needed to fix a bug in the prompt loop.
function gbc {
# Fetch and prune remote-tracking branches
git fetch -p
# Get all local branches with gone remote tracking branches
$branches = git for-each-ref --format '%(refname) %(upstream:track)' refs/heads |
Where-Object { $_ -match '\[gone\]' } |
ForEach-Object {
$_ -replace '^refs/heads/(\S+).*', '$1'
}
foreach ($branch in $branches) {
$to_delete = $false
$need_response = $true
while ($need_response) {
$response = Read-Host "delete $branch (y/n)"
switch ($response) {
{ $_ -in 'y', 'Y' } {
Write-Host "Okay"
$to_delete = $true
$need_response = $false
}
{ $_ -in 'n', 'N' } {
Write-Host "Not deleting"
$to_delete = $false
$need_response = $false
}
default {
Write-Host "Not valid input"
# Continue the while loop
}
}
}
if ($to_delete) {
git branch -D $branch
}
}
}
Bash/ZSH etc
This was also written by Claude, and it works as is. You can add it to ~/.bashrc or ~/.zshrc.
gbc() {
# Fetch and prune remote-tracking branches
git fetch -p
# Get all local branches with gone remote tracking branches
local branches=$(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}')
# Process each branch
for branch in $branches; do
local to_delete=false
while true; do
# Read user input
read -n 1 -p "delete $branch (y/n) " response
echo # Add newline after response
# Check if read was aborted (Ctrl+D returns exit code 1)
if [ $? -ne 0 ]; then
echo
return 1
fi
case "$response" in
y|Y)
echo "Okay"
to_delete=true
break
;;
n|N)
echo "Not deleting"
to_delete=false
break
;;
*)
echo "Not valid input"
# Continue the while loop
;;
esac
done
if [ "$to_delete" = true ]; then
git branch -D "$branch"
fi
done
}