Skip to content

Instantly share code, notes, and snippets.

@dominics
Created February 7, 2012 22:53
Show Gist options
  • Save dominics/1762685 to your computer and use it in GitHub Desktop.
Save dominics/1762685 to your computer and use it in GitHub Desktop.
A quick bash script to remove stale remote branches (merged into master, head commit is old) by pushing an empty reference to them
#!/bin/bash
# vim: set ts=4 sw=4 expandtab tw=79 :
#
# Asks to delete remote branches that have been merged into master and haven't
# been committed to in a fortnight. Also asks to delete unmerged branches that
# haven't been committed to in three months.
set -e
c_red=`tput setaf 1 || tput setf 4`
c_yellow=`tput setaf 3 || tput setf 6`
c_reset=`tput sgr0`
two_weeks_ago=$(date -v-2w +%s)
three_months_ago=$(date -v-3m +%s)
iso_8601="%Y-%m-%d %H:%M:%S %z"
merged_branches=$( \
git branch -ar --merged master --no-color --no-abbrev | \
grep -v -- '->' | \
grep -v 'master' | \
grep -v 'prod' | \
grep -v 'staging' | \
grep -Pv '\sfeature\s' | \
grep '/'
)
unmerged_branches=$( \
git branch -ar --no-merged master --no-color --no-abbrev | \
grep -v -- '->' | \
grep -v 'master' | \
grep -v 'prod' | \
grep -v 'staging' | \
grep -Pv '\sfeature\s' | \
grep '/'
)
IFS="
"
for branch in $merged_branches; do
echo "Branch: $c_yellow$branch$c_reset"
remote=$(sed 's/ \([A-Za-z0-9_-]*\)\/.*/\1/' <<< "$branch" | tr -d ' ')
name=$(sed 's/.*\/\([A-Za-z0-9_-]*\)/\1/' <<< "$branch")
last=$(git show -s --format="%ci" $remote/$name | tr -d '\n')
last_timestamp=$(date -jf "$iso_8601" "$last" +%s)
echo " Last commit: $last"
if [[ $last_timestamp -gt $two_weeks_ago ]]; then
echo " Has commit in last fortnight. Skipping."
continue
else
remove=""
while [[ $remove != "y" && $remove != "n" ]]; do
read -p " No commit in last fortnight. Remove branch? (y/n) " remove
done
if [[ $remove == "n" ]]; then
continue
fi
fi
echo " Removing branch: git push $remote :$name"
git push $remote ":$name"
done
for branch in $unmerged_branches; do
echo "Unmerged branch: $c_red$branch$c_reset"
remote=$(sed 's/ \([A-Za-z0-9_-]*\)\/.*/\1/' <<< "$branch" | tr -d ' ')
name=$(sed 's/.*\/\([A-Za-z0-9_-]*\)/\1/' <<< "$branch")
last=$(git show -s --format="%ci" $remote/$name | tr -d '\n')
last_timestamp=$(date -jf "$iso_8601" "$last" +%s)
number_commits=$(git rev-list $remote/$name ^master | wc -l | tr -d ' ')
echo " Last commit: $last"
echo " Number of commits: $number_commits"
if [[ $last_timestamp -gt $three_months_ago ]]; then
echo " Has commit in last three months. Skipping."
continue
else
remove=""
while [[ $remove != "y" && $remove != "n" ]]; do
read -p " No commit in last three months. Remove branch? (y/n) " remove
done
if [[ $remove == "n" ]]; then
continue
fi
fi
echo " Removing branch: git push $remote :$name"
git push $remote ":$name"
done
echo "All done. Remember to git remote prune $remote"
@kunkun-tang
Copy link

How to use this script? Tried but didn't work.
→ ./clean.sh usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]] [-e pattern] [-f file] [--binary-files=value] [--color=when] [--context[=num]] [--directories=action] [--label] [--line-buffered] [--null] [pattern] [file ...]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment