Skip to content

Instantly share code, notes, and snippets.

@gparlakov
Forked from manofearth/delete-stale-branches.sh
Last active July 17, 2023 02:29
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save gparlakov/b1acc804e0140b7a126cb5b9685933a7 to your computer and use it in GitHub Desktop.
Save gparlakov/b1acc804e0140b7a126cb5b9685933a7 to your computer and use it in GitHub Desktop.
Delete Stale Branches
#!/usr/bin/env bash
while getopts "d" opt; do
case $opt in
d) dryRunOpt="--dry-run";;
esac
done
# prune local "cache" of remote branches first:
git fetch --prune origin
# delete merged to master branches:
mergedBranches=$(git branch -r --merged origin/master | grep "^ origin/" | cut -d/ -f2- | grep -v -e "^master$" -e "^HEAD -> origin/master$")
if [ -n "${mergedBranches}" ]; then
echo -e "\033[0;32mDeleting merged branches...\033[0m"
git push $dryRunOpt --delete origin ${mergedBranches}
fi
# delete branches with last (cherry picked) commit older than 5 months:
echo -e "\033[0;32mSearching for stale branches...\033[0m"
staleTimestamp=$(date -d "now - 5 months" +"%s")
maybeStaleTimestamp=$(date -d "now - 2 weeks" +"%s")
notMergedBranches=$(git branch -r --no-merged origin/master | grep "^ origin/")
branchesToDelete=""
branchesToReview=""
for branch in ${notMergedBranches}; do
lastCommitInfo=$(git cherry origin/master ${branch} | grep -v "^-" | cut -d" " -f2 | xargs git show --format="%H|%ct|%cr|%an" --quiet | grep -v "^$(git rev-parse HEAD)" | tail -1)
lastCommitTimestamp=$(echo "${lastCommitInfo}" | cut -d"|" -f2)
if [ -z "${lastCommitTimestamp}" ] || [ ${lastCommitTimestamp} -lt ${staleTimestamp} ]; then
branchesToDelete+=" ${branch#origin/}"
elif [ ${lastCommitTimestamp} -lt ${maybeStaleTimestamp} ]; then
branchesToReview+="${branch#origin/}|${lastCommitInfo}"$'\n'
fi
echo -n .
done
echo # for new line after dots
if [ -n "${branchesToDelete}" ]; then
echo -e "\033[0;32mDeleting stale branches...\033[0m"
git push $dryRunOpt --delete origin ${branchesToDelete}
else
echo -e "\033[0;32mNo stale branches...\033[0m"
fi
echo -e "\033[1;33mBranches to review (may be stale):\033[0m"
echo "${branchesToReview}" | sort -t"|" -k5 | awk -F"|" 'NF {print $5 " changed branch \"" $1 "\" in project \"'${PWD##*/}'\" " $4}'
@arul2arul
Copy link

Found if in case of lastCommitTimestamp is NULL, still it pass through and assign to branchesToDelete, hence have gone approach as below:

if [[ ! -z "$lastCommitTimestamp" ]] && [[ ${lastCommitTimestamp} -lt ${staleTimestamp} ]]; then

@gparlakov
Copy link
Author

@arul2arul thanks!

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