Skip to content

Instantly share code, notes, and snippets.

@douglascayers
Last active March 7, 2025 18:26
Show Gist options
  • Save douglascayers/661eef9ff9f45a49b2025f6cbdc5679e to your computer and use it in GitHub Desktop.
Save douglascayers/661eef9ff9f45a49b2025f6cbdc5679e to your computer and use it in GitHub Desktop.
Delete local branches that no longer exist on a remote
#!/bin/bash
# https://gist.github.com/douglascayers/661eef9ff9f45a49b2025f6cbdc5679e
set -e
# Get the name of the currently checked out branch.
current_branch=$(git branch --show-current)
# Delete all local branches whose remote branch no longer exists, excluding the current branch.
orphaned_branches=$(git branch -v | grep -E "[0-9a-zA-Z]{7} \[gone\]" | awk '{ if ($1 == "*") print $2; else print $1 }' | grep -Ev "^(${current_branch}|\+)$" || true)
if [ -n "$orphaned_branches" ]; then
echo "$orphaned_branches" | xargs git branch -D $1
fi
# The commmand explained:
#
# List all branches. The -v flag will include "[gone]" in the output if the remote tracked branch no longer exists.
# git branch -v
#
# Next filter rows that indicate their remote tracked branch no longer exists.
# The regex matches on the commit hash then the phrase "[gone]".
# grep -E "[0-9a-zA-Z]{7} \[gone\]"
#
# For each matched row, pull the first column, which is the local branch name.
# Also account for the checked out branch name prefixed with an asterisk.
# awk '{ if ($1 == "*") print $2; else print $1 }'
#
# Exclude the currently checked out branch from the list of branches to delete.
# Exclude any branches checked out as worktrees (+ sign), as you need to delete them separately.
# And if that would cause grep to emit nothing then return true to ignore error code.
# grep -Ev "^(${current_branch}|\+)$" || true
#
# Lastly, pass each branch name to the git branch delete command.
# xargs git branch -D $1
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment