Skip to content

Instantly share code, notes, and snippets.

@shadowhand
Last active August 14, 2025 19:38
Show Gist options
  • Select an option

  • Save shadowhand/9813453 to your computer and use it in GitHub Desktop.

Select an option

Save shadowhand/9813453 to your computer and use it in GitHub Desktop.
Fast git branch switching (git-switchbranch)
#!/bin/bash
######################################################################################
# THIS GIST IS NO LONGER MAINTAINED AND MAY BE DELETED IN THE FUTURE! #
# PLEASE GO TO https://github.com/shadowhand/git-switchbranch FOR A CURRENT VERSION! #
######################################################################################
# git-switchbranch
# @link https://gist.github.com/shadowhand/9813453
# @author shadowhand https://github.com/shadowhand
# @license MIT
#
# installation:
# save this file as git-switchbranch somewhere in your $PATH
# make it executable: chmod +x git-switchbranch
#
# optional:
# git config --global alias.sb '! git switchbranch'
#
# usage:
# git switchbranch
# select the branch you want to move to using numbers
# press enter
# ???
# profit
#
# enjoy!
#
usage() {
echo "usage: git switchbranch [-a] [-r <remote>]"
}
# changelog
#
# 0.0.4
# - update prompt
#
# 0.0.3
# - update comments, documentation
# - fix select menu issues when in detached HEAD mode
# - added new options -a, -r $remote for selecting non-local branches
#
# 0.0.2
# - branch named "master" will always be first in menu
#
# 0.0.1
# - initial release
#
version() {
echo "switchbranch v0.0.4"
}
_select_branch() {
# First branch is always set to "master", or whatever local branch is first when looking for master
# Search all branches, not just local?
local branchargs="--list"
local remote=""
while getopts "r:a" o; do
case $o in
"a")
# select all branches
branchargs="$branchargs -a"
;;
"r")
# show a specific remote
branchargs="$branchargs -r"
remote="$OPTARG"
;;
esac
done
# branch names, removing detached and no branch warnings, and also trimming whitespace
if [[ ! -z $remote ]]; then
local branches=($(git branch $branchargs | grep -v -e '\->' -e '\* (detached from .*)' -e '(no branch)' | grep "$remote/" | sed -e 's/*//' -e 's/^[ \t]+//'))
else
local branches=($(git branch $branchargs | grep -v -e '\->' -e '\* (detached from .*)' -e '(no branch)' | sed -e 's/*//' -e 's/^[ \t]+//'))
fi
if [[ ! -z $remote ]]; then
# remove the remote from the branch name
branches=(${branches[@]/$remote\//})
fi
for (( i=0; i < ${#branches[@]}; i++ )); do
# attempt to find a master branch
if [[ "${branches[$i]}" == *"master" ]]; then
local master="${branches[$i]}"
unset branches[$i]
break # found one, stop looking
fi
done
if [[ ! -z $master ]]; then
# ensure that master branch is placed in front
branches=("$master" "${branches[@]}")
fi
# Set the prompt string
PS3="--> Switch branch [1-${#branches[@]}] or [q]? "
# ask for input!
select selected in ${branches[@]}; do
if [ "$selected" == "quit" -o "$selected" == "q" -o "$selected" == "" ]; then
exit 1
fi
git checkout "$selected"
exit 0
done
}
main() {
local command="$1"
case $command in
"version") version;;
*) _select_branch "$@";;
esac
}
main "$@"
@shadowhand
Copy link
Copy Markdown
Author

screenshot of ui, such as it is

v0.0.4

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