Skip to content

Instantly share code, notes, and snippets.

@mikybars
Last active October 1, 2021 14:40
Show Gist options
  • Save mikybars/cd3a7d20b5846a2918a0e3a293fb3f1e to your computer and use it in GitHub Desktop.
Save mikybars/cd3a7d20b5846a2918a0e3a293fb3f1e to your computer and use it in GitHub Desktop.
[Git interactive branch filter with hot reloading] Git helper script that lists remote branches sorted by their last update time. The branch list is fed into a fuzzy finder for interactive filtering and the selected branch is checked out. Finally a keyboard shortcut enables dynamic reloading of the branches after fetching the remote. #shell #fzf…
#!/usr/bin/env bash
# git-change
#
# Git helper script that lists remote branches sorted by their last update time. The branch list is fed
# into a fuzzy finder for interactive filtering and the selected branch is checked out. Finally a
# keyboard shortcut enables dynamic reloading of the branches after fetching the remote.
# External dependencies:
# - fzf: brew install fzf
# - arrow: pip3 install arrow
# - gsed: brew install gnu-sed
# - gstat, gdate: brew install coreutils
LIST_CMD='
red() {
echo "$(tput setaf 1)$1$(tput sgr0)"
}
green() {
echo "$(tput setaf 2)$1$(tput sgr0)"
}
dim() {
echo "$(tput setaf 8)$1$(tput sgr0)"
}
date_before() {
ts="$1"
instant="$2"
[[ $(gdate -d@$ts --iso-8601=seconds) < $(gdate -d "$instant" --iso-8601=seconds) ]]
}
header() {
last_git_fetch_ts=$(gstat -c %Y $(git rev-parse --show-toplevel)/.git/FETCH_HEAD)
last_git_fetch_human=$(python3 -c "import arrow; print(arrow.get($last_git_fetch_ts).humanize());")
if date_before $last_git_fetch_ts "1 hour ago"; then
red " Last fetch was $last_git_fetch_human (CTRL-F to fetch) "
else
green " Last fetch was $last_git_fetch_human (CTRL-F to fetch) "
fi
}
git for-each-ref \
--sort="-authordate" --shell \
--format="date=%(authordate:relative) ref=%(refname:lstrip=3) author=%(authorname)" \
refs/remotes |
while read entry; do
eval "$entry"
[[ $ref == HEAD ]] && continue;
first_name=${author%% *}
date=$(dim "$date")
echo "$ref:$first_name:|:$date"
done |
column -s ":" -t |
gsed "s/\b\(develop\|master\)\b/$(tput setaf 3)\1$(tput sgr0)/" | # colorize protected branches
gsed "1 i\\$(header)"
'
branch=$(eval "$LIST_CMD" | fzf --ansi --no-info --height=50% \
--color="header:reverse" --header-lines=1 \
--tiebreak=index \
--bind "ctrl-f:reload(git fetch && $LIST_CMD)" \
--nth=1,2) # filter only by ref name & author name
if (( $? == 0 )); then
git switch $(awk '{print $1}' <<<$branch)
fi
# vim: set ft=bash:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment