Skip to content

Instantly share code, notes, and snippets.

@kenbellows
Last active March 7, 2022 14:56
Show Gist options
  • Save kenbellows/59cffacd94164b83998111e118b6b482 to your computer and use it in GitHub Desktop.
Save kenbellows/59cffacd94164b83998111e118b6b482 to your computer and use it in GitHub Desktop.
Git shorcuts for bash
# simple aliases
alias gA="git add -A"
alias gc="git commit"
alias gcm="git commit -m"
alias gcam="git commit -am"
alias gcp="git cherry-pick"
alias gcob="git checkout -b"
alias gb="git branch --show-current"
alias gp="git push"
# Checkout by substring! Great for branches named with ticket numbers,
# e.g. "gco 1234" instead of "git checkout feature/PROJ-1234"
function gco() {
if [ $1 == '-' ] ; then
git checkout -
else
if [[ $1 =~ .*release.* ]] ; then
branch=$(git branch | grep $1 | head -1)
else
branch=$(git branch | grep -v release | grep $1 | head -1)
fi
if [ -z "$branch" ] ; then
branch=$(git branch -r | grep -v release | grep $1 | head -1 | sed 's/^\s*origin\///')
fi
if [-z "$branch" ] ; then
branch="$1"
fi
git checkout $branch
fi
}
# glog: git log with my preferred oneline format
alias glog='git log --pretty-format:"%C(yellow)%h %C(cyan)%<(24)%ad %Cgreen%an%C(auto)%d%Creset: %s" --date=local'
#gl: glog, but only the most recent 10 commits
alias gl="glog -10"
export GIT_PAGER="less --raw"
# shorthand python script for 'git status', including numbered modifications for use with 'gdiff' defined below
gitstatus_pyscript="
import sys, re
n = 0
def markline(line):
global n
if re.match(r'^#?\\s*\\S*modified:', line):
n += 1
return line.replace('modified:', ' '*(4 - len(str(n))) + str(n) + ' modified:')
else:
return line
print ''.join(map(markline, sys.stdin))
"
function gstatus() {
git -c color.status=always status | python -c "$gitstatus_pyscript"
}
alias gs=gstatus
# wrapper for 'git diff' that allows specifying an index to the modified file to diff, as specified by 'gstatus' above
function __gdiff() {
if [[ $1 == '-w' ]] ; then
opts='--word-diff'
i=$2
else
opts=
i=$1
fi
if [[ $i =~ ^[0-9]+$ ]] ; then
if [[ $i == 0 ]] ; then
>&2 echo "modification indices are 1-based; please provide a non-zero index"
return 2
fi
case "$i" in
1) suff=st ;;
2) suff=nd ;;
3) suff=rd ;;
*) suff=th ;;
esac
echo diffing $i$suff modified file
#locate the $ith modified file in the output of git status
file=$(git -c color.status=never status | egrep '^#?\s*modified:\s' | sed 's/^#\?\s*modified:\s*//' | sed -n "${i}p")
echo file: $file
else
echo diffing $i
file=$i
fi
# get the colorized version of the file: green files are staged for commit, red are unstaged
red=$(echo -e "\e[31m")
green=$(echo -e "\e[32m")
reset=$(echo -e "\e[0m")
if [[ $file ]] ; then
colored_file=$(git -c color.status=always status | grep "$file" | sed 's/^#\?\s*\(\S*\)modified:\s*/\1/')
else
colored_file=
fi
# check the color produced by git status; green files are staged, so we need to use git diff --cached
if [[ $colored_file ]] ; then
if [[ $(echo $colored_file | grep -F $green) ]] ; then
opts=$opts' --cached'
fi
cmd="git diff --color $opts"
echo $cmd $colored_file
$cmd $file
# if $file is a file pattern, e.g. *.js, then the above won't match anything specific and we won't know
# whether or not we need the --cached flag; this requires some different processing
else
cmd="git diff --color $opts"
# try diffing both with and without --cache; there may be output from either or both
staged=$(2>&1 $cmd --cached $file)
unstaged=$(2>&1 $cmd $file)
# staged?
if [[ $staged ]] ; then
echo $green'== Staged: =='$reset
echo "$staged"
echo
# add an extra line break between staged and unstaged
if [[ $unstaged ]] ; then
echo
fi
fi
if [[ $unstaged ]] ; then
echo $red'== Unstaged: =='$reset
echo "$unstaged"
fi
if [[ ! $staged && ! $unstaged ]] ; then
echo No output
fi
fi
}
# always pipe git diff output into less
function gdiff() {
__gdiff "$@" | less --raw --quit-if-one-screen
}
alias gd=gdiff
# wrapper for 'git add' that allows specifying an index to the modified file to add, as speficied by 'gstatus' above
function gadd() {
for i in "$@" ; do
if [[ $i =~ ^[0-9]+$ ]] ; then
if [[ $i == 0 ]] ; then
>&2 echo "modification indices are 1-based; please provide a non-zero index"
return 2
fi
case "$i" in
1) suff=st ;;
2) suff=nd ;;
3) suff=rd ;;
*) suff=th ;;
esac
# locate the $ith modified file in the output of git status
file=$(git -c color.status=never status | egrep '^#?\s*modified:\s' | sed 's/^#\?\s*modified:\s*//' | sed -n "${i}p")
echo adding $i$suff modified file: $file
else
file=$i
fi
if [[ $file ]] ; then
git add $file
else
>&2 echo "could not match index \"$i\" to a file"
return 3
fi
done
}
alias ga=gadd
# Go back to project root by recursively checking parent dir for .git
# Credit: Laura Ramsey 🦖 on Twitter (@lramsey_95)
# https://twitter.com/lramsey_95/status/1202464219947364352
function c() {
if [ -d ".git" ] ; then
cd "$(pwd)";
else
cd ..;
c;
fi
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment