Skip to content

Instantly share code, notes, and snippets.

@sephraim
Last active December 5, 2023 22:11
Show Gist options
  • Save sephraim/6d717dcf66509fcd889ac637ce58f3d2 to your computer and use it in GitHub Desktop.
Save sephraim/6d717dcf66509fcd889ac637ce58f3d2 to your computer and use it in GitHub Desktop.
[Tidy up Git branches] Delete & prune local/remote branches #git
#!/usr/bin/env bash
set -u
########################################################################################################################
# git-tidy
#
# Delete any branch that has been merged into a base branch ('main', 'master', or 'develop')
# unless it's a protected branch or the current branch. Delete both in local and remote.
#
# Usage:
# $ ./git-tidy
#
# Or if this script (git-tidy, no .sh extension) is in your $PATH, then run:
# $ git tidy
########################################################################################################################
echo "DELETING MERGED BRANCHES..."
echo ""
base_branches=(main master develop)
current_branch="$(git branch --show-current)"
protected_branches=("${current_branch}" "${base_branches[@]}")
merged_branches=''
# Prune all stale remote tracking branches
git fetch origin --prune
# Get unique array of all branches that have been merged into the base branches
for branch in "${base_branches[@]}"; do
merged_branches="${merged_branches} $(git branch --merged ${branch} 2>/dev/null | tr -d '*' | tr -d ' ')"
merged_branches="${merged_branches} $(git branch --merged origin/${branch} 2>/dev/null | tr -d '*' | tr -d ' ')"
done
merged_branches=$(echo $merged_branches | tr ' ' '\n' | sort -u | tr '\n' ' ') # Remove duplicates
read -ra merged_branches <<< "${merged_branches}" # Convert to array
# Iterate through each merged branch and delete it (unless it's a current / protected branch)
for branch in "${merged_branches[@]}"; do
if [[ ! " ${protected_branches[@]} " =~ " $branch " ]]; then
echo "- DELETING: $branch"
git branch -d "${branch}" # Delete local branch
git push origin --delete "${branch}" 2>/dev/null # Delete remote branch (if it exists)
elif [[ "$branch" == "$current_branch" ]]; then
echo "- SKIPPING: $branch [*CURRENT*]"
else
echo "- SKIPPING: $branch [*PROTECTED*]"
fi
done
# Prune all stale remote tracking branches again
git fetch origin --prune
echo ""
echo "DONE!"
echo ""
echo "REMAINING LOCAL BRANCHES:"
echo "$(git branch)"
if [[ ! " ${base_branches[@]} " =~ " ${current_branch} " ]]; then
echo ""
echo "NOTE:"
echo "You are currently on branch '${current_branch}', which was not deleted."
echo "To delete it, switch to one of the following branches and try again: ${base_branches[*]}"
fi
# Delete remote branches that have been merged into 'origin/develop' (besides current, 'origin/develop' and 'origin/master')
git pull --rebase upstream develop:develop
git push origin develop:develop
git remote prune origin
git branch -r --merged origin/develop | grep -wv 'master\|develop' | sed 's/^origin\///' | xargs -n 1 git push -d origin
git remote prune origin
# Delete local branches that have been merged into 'develop' (besides current, 'develop' and 'master' branches)
git branch --merged develop | grep -wv '\*\|master\|develop' | xargs -n 1 git branch -d
git push origin -d LOCAL_BRANCH # remove remote branch tracked by local branch
git remote prune origin # remove *references* (refs/remotes/…) for remote branches
# that no longer exist (run `git branch -a` before and after
# to see the difference.
git branch -d LOCAL_BRANCH # remove branch locally
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment