Last active
March 7, 2022 14:56
-
-
Save kenbellows/59cffacd94164b83998111e118b6b482 to your computer and use it in GitHub Desktop.
Git shorcuts for bash
This file contains 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
# 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