Skip to content

Instantly share code, notes, and snippets.

@pnovotnak
Last active March 23, 2023 06:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pnovotnak/4dfe9b2867bf6fea60fa94b4c8a2cc9d to your computer and use it in GitHub Desktop.
Save pnovotnak/4dfe9b2867bf6fea60fa94b4c8a2cc9d to your computer and use it in GitHub Desktop.
List most recently used branches, with option to check out
#!/usr/bin/env bash
# Requires bash 4+ (not shipped with macos)
set -e
set -o pipefail
most_recent_branches() {
git reflog show --pretty=format:'%gs ~ %gd' --date=relative \
| grep 'checkout:' | grep -oE '[^ ]+ ~ .*' \
| awk -F~ '!seen[$1]++'
}
get_all_branches() {
git for-each-ref --format='%(refname:short)' refs/heads/
}
filter_non_existent_branches() {
# Build a set of branches, calling `git` only once
declare -lA branch_set=()
while read -r branch; do
branch_set["$branch"]=true
done < <(get_all_branches)
readonly branch_set
while read -r line; do
branch="$(echo "$line" | awk '{print $1}')"
# Breaks because of ANSI codes
if [ "${branch_set["$branch"]}" ]; then
echo "$line"
fi
done
}
get_most_recent_existing_branches() {
most_recent_branches \
| filter_non_existent_branches
}
pretty_print_reflog() {
awk -F' ~ HEAD@{' '{printf(" \033[33m%s: \033[37m %s\033[0m\n", substr($2, 1, length($2)-1), $1)}'
}
pick_branch() {
pretty_print_reflog \
| fzf \
| awk '{print $NF}'
}
CHECKOUT=false
PICKER=false
VERBOSE=false
readonly FLAGS="chpv"
usage() {
local exit_code="$1"
cat <<EOF
$(basename $0) [$FLAGS]
-c pick a branch and check it out (infers -p)
-h print this help and exit with status 0
-p invoke fzf to pick a branch
-v verbose
EOF
exit "$exit_code"
}
parse_args() {
while getopts "$FLAGS" flag; do
# stored in $OPTARG
case "${flag}" in
c) CHECKOUT=true ;;
p) PICKER=true ;;
v) VERBOSE=true ;;
h) usage 0 ;;
*)
usage 1
;;
esac
done
# Checkout infers picker.
$CHECKOUT && PICKER=true
readonly CHECKOUT
readonly PICKER
readonly VERBOSE
}
main() {
parse_args "$@"
$VERBOSE && set -x
local chosen_branch
# We need the output in the current shell, so run the branch refinement logic
# in a subshell, processing the results here.
{
if $PICKER; then
chosen_branch=$(pick_branch)
else
pretty_print_reflog
fi
} < <(
get_most_recent_existing_branches
)
if $CHECKOUT; then
git checkout "$chosen_branch"
fi
}
main "$@"
@pnovotnak
Copy link
Author

I use this in two git aliases:

  • git lb (git-lb)
  • git sb (git-lb -p)

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