Last active
October 1, 2021 14:40
-
-
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…
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
#!/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