Skip to content

Instantly share code, notes, and snippets.

@jordan-brough
Last active September 11, 2024 21:46
Show Gist options
  • Save jordan-brough/48e2803c0ffa6dc2e0bd to your computer and use it in GitHub Desktop.
Save jordan-brough/48e2803c0ffa6dc2e0bd to your computer and use it in GitHub Desktop.
Git: Display a list of recently checked out branches/tags/commits
#!/usr/bin/env bash
# Source: https://gist.github.com/jordan-brough/48e2803c0ffa6dc2e0bd
# See also: https://stackoverflow.com/a/25095062/58876
# Download this script as "git-recent" (no extension), chmod it to be executable and put it in your
# path somewhere (e.g. /usr/bin). You can then use it via `git recent` from inside any git repo.
# Examples:
# Interactive prompt for most recent 4 branches:
# $ git recent -n 5
# 1) master 4) deleted-branch
# 2) stable 5) improve-everything
# 3) fun
# Choose a branch: 2
# List mode (non-interactive):
# $ git recent -n 5 -l
# master
# stable
# fun
# deleted-branch
# improve-everything
# Verify branch existence:
# $ git recent -n 5 -l -e
# master
# stable
# fun
# improve-everything
# something-else
# # (notice "deleted-branch" removed from results)
# Contributors:
# - jordan-brough
# - fritz-c
usage()
{
echo "usage: git recent [-n lines] [-l] [-e]"
}
while getopts "hn:le" opt; do
case $opt in
h) # help
usage
exit 1
;;
n) # number of results
NUM=$OPTARG
;;
l) # list mode (non-interactive)
INTERACTIVE=0
;;
e) # validate existence
CHECK_EXISTENCE=1
;;
\?)
usage
exit 1
;;
esac
done
NUM=${NUM-10} # default to 10 lines
INTERACTIVE=${INTERACTIVE-1} # default to interactive
CHECK_EXISTENCE=${CHECK_EXISTENCE-0} # default to *not* checking existence (faster)
BRANCHES=(
$(git reflog |
egrep -io "moving from ([^[:space:]]+)" |
awk '{ print $3 }' | # extract 3rd column
awk ' !x[$0]++' | # Removes duplicates. See http://stackoverflow.com/questions/11532157
egrep -v '^[a-f0-9]{40}$' | # remove hash results
while read line; do # verify existence
([[ $CHECK_EXISTENCE = '0' ]] || git rev-parse --verify "$line" &>/dev/null) && echo "$line"
done |
head -n "$NUM"
)
)
if [[ $INTERACTIVE = '1' ]]; then
PS3="Choose a branch: "
select d in "${BRANCHES[@]}"; do
test -n "$d" && break;
echo ">>> Invalid Selection";
done
git checkout "$d"
else
printf '%s\n' "${BRANCHES[@]}"
fi
@kerryj89
Copy link

kerryj89 commented Apr 26, 2023

@crazyones110 To force a checkout, but in hindsight this is quite dangerous as we wouldn't know what's stopping us from switching branch on the first run so nvm. What would be nicer is if the script warns you about uncommitted changes and then follows up with asking if you want to force checkout anyway because a lot of times what stops me are silly things like lockfiles after installing depenendencies, e.g.

Choose a branch: 1
error: Your local changes to the following files would be overwritten by checkout:
        yarn.lock
Please commit your changes or stash them before you switch branches.
Aborting

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