Last active
October 8, 2021 02:39
-
-
Save kikuchi-m/55028305055a3637d1ab711cece988f9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| USAGE="usage: git delete-merged-branches | |
| [(-r|--remote) <remote-name>] | |
| [(-b|--branch) <merge-base>] | |
| [(-s|--older-than) <date>] | |
| [--local-only] [--yes] [-n|--dry-run]" | |
| for (( i = 1; i < $(($#+1)); ++i )); do | |
| # echo "(option ${@:$i:1})" | |
| case "${@:$i:1}" in | |
| -r|--remote) | |
| REMOTE="${@:$((++i)):1}" | |
| ;; | |
| -b|--branch) | |
| BASE="${@:$((++i)):1}" | |
| ;; | |
| -s|--older-than) | |
| OLDER_THAN="${@:$((++i)):1}" | |
| ;; | |
| --local-only) | |
| LOCAL_ONLY=1 | |
| ;; | |
| --yes) | |
| CONTINUE=yes | |
| ;; | |
| -n|--dry-run) | |
| DRY_RUN=-n | |
| ;; | |
| -h|--help) | |
| cat <<< $USAGE | |
| exit 0 | |
| ;; | |
| *) | |
| echo "unknown option ${@:$i:1}">&2 | |
| echo $USAGE>&2 | |
| exit 1 | |
| ;; | |
| esac | |
| done | |
| # REMOTE: remote name | |
| if [ ! $LOCAL_ONLY ]; then | |
| if [ -z "$REMOTE" ]; then | |
| REMOTE=origin | |
| read -p "remote ($REMOTE): " REMOTE | |
| fi | |
| if [ -z "$REMOTE" ]; then | |
| REMOTE=origin | |
| else | |
| if [ ! $(git remote | grep -e "^$REMOTE\$") ]; then | |
| echo "not found: $REMOTE" | |
| exit 1 | |
| fi | |
| fi | |
| fi | |
| # BASE: base branch/commit | |
| if [ -z "$BASE" ]; then | |
| if [ -z "$REMOTE" ]; then | |
| BASE=master | |
| else | |
| BASE=$REMOTE/master | |
| fi | |
| read -p "base ($BASE): " BASE | |
| fi | |
| if [ -z "$BASE" ]; then | |
| if [ -z "$REMOTE" ]; then | |
| BASE=master | |
| else | |
| BASE=$REMOTE/master | |
| fi | |
| elif [[ $BASE =~ ^HEAD ]]; then | |
| BASE=$(git rev-parse $BASE) | |
| elif [ -z $(git branch --all --list $BASE) ]; then | |
| echo "branch not found: $BASE" | |
| exit 1 | |
| fi | |
| # OLDER_THAN: to remove branch older than | |
| if [ -z "$OLDER_THAN" ]; then | |
| OLDER_THAN="4 months ago" | |
| read -p "older than ($OLDER_THAN): " OLDER_THAN | |
| fi | |
| if [ -z "$OLDER_THAN" ]; then | |
| OLDER_THAN="4 months ago" | |
| fi | |
| if [ ! "$LOCAL_ONLY" -o -n "$REMOTE" ]; then | |
| REMOTE_REF=refs/remotes/$REMOTE/ | |
| fi | |
| REFS=$(git for-each-ref \ | |
| --format="%(refname:short)" \ | |
| --sort=committerdate \ | |
| --merged $BASE \ | |
| $REMOTE_REF refs/heads/) | |
| REFS=$(cat <<< $REFS | grep -v "$BASE" | grep -v "$REMOTE/master" | grep -v HEAD) | |
| LOGFMT="%C(red)%h%Creset %C(cyan)%ci%Creset %C(green)(<branch>)%Creset %C(yellow)%cn%Creset %s" | |
| TARGETS= | |
| for BRANCH in $REFS; do | |
| P=$(sed "s|<branch>|$BRANCH|" <(echo "$LOGFMT")) | |
| if [ -n "$(git log -1 --oneline --since="$OLDER_THAN" $BRANCH)" ]; then | |
| git log -1 --pretty="remaining: $P" $BRANCH | |
| else | |
| git log -1 --pretty="deleting: $P" $BRANCH | |
| TARGETS="$TARGETS | |
| $BRANCH" | |
| fi | |
| done | |
| if [ -z "$TARGETS" ]; then | |
| echo no branch to delete | |
| exit 0 | |
| fi | |
| if [ -z "$DRY_RUN" -a "$CONTINUE" != "yes" ]; then | |
| echo "delete branches..." | |
| read -p "continue? (yes/No): " CONTINUE | |
| fi | |
| CONTINUE=$(echo $CONTINUE | tr '[:upper:]' '[:lower:]') | |
| if [ -z "$DRY_RUN" -a "$CONTINUE" == yes ]; then | |
| echo continue... | |
| for BRANCH in $TARGETS; do | |
| if [ -n "$REMOTE" ]; then | |
| if [[ "$BRANCH" =~ ^$REMOTE ]]; then | |
| git push $DRY_RUN $REMOTE :$(echo $BRANCH | sed "s/$REMOTE\///") | |
| continue | |
| fi | |
| fi | |
| if [ -n "$DRY_RUN" ]; then | |
| echo git branch -D $BRANCH | |
| else | |
| git branch -D $BRANCH | |
| fi | |
| done | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment