Skip to main content

git/cleanup_branches

1#!/usr/bin/env bash
2# This script cleans up local Git branches which have been merged into
3# the main branch. I use it to clean up the branch view in GitUp
4# (my Git GUI of choice), so I'm not distracted by lots of old branches.
5#
6# It's based on the commands from this Stack Overflow post:
7# https://stackoverflow.com/a/6127884/1558022
9set -o errexit
10set -o nounset
12GIT_ROOT=$(git rev-parse --absolute-git-dir)
14if [[ -f "$GIT_ROOT/refs/remotes/origin/HEAD" ]]
15then
16 PRIMARY_BRANCH=$(cat "$GIT_ROOT/refs/remotes/origin/HEAD" \
17 | tr '/' ' ' \
18 | awk '{print $5}')
19elif [[ -f "$GIT_ROOT/refs/remotes/origin/live" ]]
20then
21 PRIMARY_BRANCH="live"
22else
23 PRIMARY_BRANCH="main"
24fi
26CURRENT_BRANCH=$(git branch --show-current)
28if [[ "$PRIMARY_BRANCH" = "$CURRENT_BRANCH" ]]
29then
30 print_info "-> Current branch is $CURRENT_BRANCH, which is primary"
31else
32 print_info "-> Primary branch is $PRIMARY_BRANCH"
33 print_info "-> Current branch is $CURRENT_BRANCH"
34fi
36for branch in $(git branch --merged "$PRIMARY_BRANCH" | grep -v '*')
37do
38 if [[ "$branch" == "$PRIMARY_BRANCH" ]]
39 then
40 continue
41 fi
43 if [[ "$branch" == "$CURRENT_BRANCH" ]]
44 then
45 continue
46 fi
48 git branch --delete "$branch"
49done
51# For Tailscale repos, the above check doesn't work. Branches get rebased
52# or squashed before being merged into main, so the branch never shows up
53# as merged -- it's a different commit in main and the branch.
55# Instead, look for alexc/ branches that are more than a fortnight old and
56# don't exist in the origin. These are branches I've either abandoned or
57# merged into main.
58PREFIXES=("alexc/" "danni/" "icio/" "kradalby/" "mpminardi/" "mprovost/" "zofrex/")
59DAYS_AGO=14
60THRESHOLD_DATE=$(date -v-"${DAYS_AGO}"d +%s)
62for PREFIX in "${PREFIXES[@]}"; do
63 git for-each-ref --format='%(refname:short)' refs/heads/"$PREFIX"* | while read -r branch; do
64 # If the branch still exists on GitHub, ignore it -- this is likely
65 # an active branch with an open PR.
66 if git rev-parse --verify --quiet "origin/$branch" &>/dev/null; then
67 continue
68 fi
70 # When did I last commit to this branch?
71 commit_timestamp=$(git log -1 --format="%at" "$branch")
72 if (( commit_timestamp > THRESHOLD_DATE )); then
73 continue
74 fi
76 git branch --delete --force "$branch"
77 done
78done