Skip to content

Instantly share code, notes, and snippets.

@matthewpwatkins
Last active April 2, 2024 13:06
Show Gist options
  • Save matthewpwatkins/ac6e2a4f1c50208398afe7484b24c247 to your computer and use it in GitHub Desktop.
Save matthewpwatkins/ac6e2a4f1c50208398afe7484b24c247 to your computer and use it in GitHub Desktop.
Prune remote branches
#!/bin/bash
# Usage:
# bash prune-remote-branches.sh --all-before 2023-08-01 --none-after 2021-03-01 --force
# Default values for flags
CENTRAL_BRANCH="master"
DRY_RUN=true
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-c|--central-branch)
CENTRAL_BRANCH="$2"
shift
;;
-b|--all-before)
ALL_BEFORE_DATE="$2"
shift
;;
-a|--none-after)
NONE_AFTER_DATE="$2"
shift
;;
-f|--force)
DRY_RUN=false
;;
*)
echo "Invalid option: $1"
exit 1
;;
esac
shift
done
if [[ -z "$ALL_BEFORE_DATE" && -z "$NONE_AFTER_DATE" ]]; then
echo "Must set either --all-before or --non-after"
exit 1
fi
get_all_remote_branches() {
branch_names=$(git br -r | grep -v " -> " | sed 's/^[[:space:]]*origin\///' | sort)
for branch_name in "${branch_names[@]}"; do
if [[ "$branch_name" != "CENTRAL_BRANCH" ]]; then
echo "$branch_name"
fi
done
}
for BRANCH_NAME in $(get_all_remote_branches); do
if [[ "$BRANCH_NAME" == "$CENTRAL_BRANCH" ]]; then
continue
fi
LAST_COMMIT=$(git rev-list -n 1 "origin/$BRANCH_NAME")
LAST_COMMIT_DATE=$(git show -s --format=%cd --date=format:'%Y-%m-%d' "$LAST_COMMIT")
if [[ -n "$NONE_AFTER_DATE" && "$LAST_COMMIT_DATE" > "$NONE_AFTER_DATE" ]]; then
continue
fi
should_delete_branch=false
MERGE_BASE=$(git merge-base "origin/$BRANCH_NAME" "origin/$CENTRAL_BRANCH")
if [[ "$LAST_COMMIT" == "$MERGE_BASE" ]]; then
echo "[$BRANCH_NAME]: Merged to $CENTRAL_BRANCH. Last commit: $LAST_COMMIT - $LAST_COMMIT_DATE"
should_delete_branch=true
elif [[ -n "$ALL_BEFORE_DATE" && "$LAST_COMMIT_DATE" < "$ALL_BEFORE_DATE" ]]; then
echo "[$BRANCH_NAME]: Stale. Last commit: $LAST_COMMIT - $LAST_COMMIT_DATE"
should_delete_branch=true
fi
if [ "$DRY_RUN" = false ] && [ "$should_delete_branch" = true ]; then
git push origin --delete "$BRANCH_NAME"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment