-
-
Save jordan-brough/48e2803c0ffa6dc2e0bd to your computer and use it in GitHub Desktop.
#!/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 |
If you need this for windows, it works if you use 'Git for Windows':
- create a directory C:\Users<your_username>\bin
- in Git Bash, verfify you directory is in the path: echo $PATH
- copy the above file in C:\Users<your_username>\bin\git-recent
The git recent command will be available in CMD, Powershell, Git bash
@jordan-brough Would you be okay with officially releasing this as open-source? All this means is commenting here "I release the code above under the MIT license".
@jordan-brough - This can be really useful as open source - Can you please verify the license is permissive?
Thanks! Would be nice to have a -f "force" option
@jordan-brough Thanks for the script! I've updated the script: adding q
to quit and removing -l
option, which seems more intuitive to me.
usage()
{
echo "usage: git recent [-n lines] [-e]"
}
while getopts "hn:e" opt; do
case $opt in
h) # help
usage
exit 1
;;
n) # number of results
NUM=$OPTARG
;;
e) # validate existence
CHECK_EXISTENCE=1
;;
\?)
usage
exit 1
;;
esac
done
NUM=${NUM-10} # default to 10 lines
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"
)
)
PS3="Choose a branch (or 'q' to quit): "
# Print the options with numbers
i=1
for branch in "${BRANCHES[@]}"; do
echo "$i) $branch"
i=$((i+1))
done
while true; do
# Read user input and process the choice
echo -n "$PS3"
read -r choice
if [[ "$choice" == "q" ]]; then
echo "Quitting..."
exit 0
elif [[ $choice -ge 1 && $choice -le ${#BRANCHES[@]} ]]; then
d="${BRANCHES[$((choice-1))]}"
break
else
echo ">>> Invalid Selection. Try again."
fi
done
git checkout "$d"
Thanks! Would be nice to have a -f "force" option
@kerryj89 What do you expect -f
option do?
@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
@jordan-brough Would you be okay with officially releasing this as open-source? All this means is commenting here "I release the code above under the MIT license".