function gi() {
    curl -fL https://www.toptal.com/developers/gitignore/api/"${(j:,:)@}"
}

function current_branch() {
    git branch | awk '$1 == "*" {print $2}'
}

function grename() {
    if [[ -z "$1" || -z "$2" ]]; then
        echo "Usage: $0 old_branch new_branch"
        return 1
    fi

    # Rename branch locally
    git branch -m "$1" "$2"
    # Rename branch in origin remote
    if git push origin :"$1"; then
      git push --set-upstream origin "$2"
    fi
}

alias ggpur='ggu' \
      g='git' \
      ga='git add' \
      gaa='git add --all' \
      gapa='git add --patch' \
      gau='git add --update' \
      gav='git add --verbose' \
      gam='git am' \
      gama='git am --abort' \
      gamc='git am --continue' \
      gamscp='git am --show-current-patch' \
      gams='git am --skip' \
      gap='git apply' \
      gapt='git apply --3way' \
      gbs='git bisect' \
      gbsb='git bisect bad' \
      gbsg='git bisect good' \
      gbsn='git bisect new' \
      gbso='git bisect old' \
      gbsr='git bisect reset' \
      gbss='git bisect start' \
      gbl='git blame -w' \
      gb='git branch' \
      gba='git branch --all' \
      gbd='git branch --delete' \
      gbD='git branch --delete --force'

alias gbgd='LANG=C git branch --no-color -vv | grep ": gone\]" | awk '"'"'{print $1}'"'"' | xargs git branch -d' \
      gbgD='LANG=C git branch --no-color -vv | grep ": gone\]" | awk '"'"'{print $1}'"'"' | xargs git branch -D' \
      gbm='git branch --move' \
      gbnm='git branch --no-merged' \
      gbr='git branch --remote' \
      ggsup='git branch --set-upstream-to=origin/$(current_branch)' \
      gbg='LANG=C git branch -vv | grep ": gone\]"' \
      gco='git checkout' \
      gcor='git checkout --recurse-submodules' \
      gcb='git checkout -b' \
      gcp='git cherry-pick' \
      gcpa='git cherry-pick --abort' \
      gcpc='git cherry-pick --continue' \
      gclean='git clean --interactive -d' \
      gcl='git clone --recurse-submodules'

function gccd() {
    gcl "$@" && cd "$(basename "$_")"
}
compdef _git gccd=git-clone

alias gcam='git commit --all --message' \
      gcas='git commit --all --signoff' \
      gcasm='git commit --all --signoff --message' \
      gcs='git commit --gpg-sign' \
      gcss='git commit --gpg-sign --signoff' \
      gcssm='git commit --gpg-sign --signoff --message' \
      gcmsg='git commit --message' \
      gcsm='git commit --signoff --message' \
      gc='git commit --verbose' \
      gca='git commit --verbose --all' \
      gca!='git commit --verbose --all --amend' \
      gcan!='git commit --verbose --all --no-edit --amend' \
      gcans!='git commit --verbose --all --signoff --no-edit --amend' \
      gc!='git commit --verbose --amend' \
      gcn!='git commit --verbose --no-edit --amend' \
      gcf='git config --list' \
      gdct='git describe --tags $(git rev-list --tags --max-count=1)' \
      gd='git diff' \
      gdca='git diff --cached' \
      gdcw='git diff --cached --word-diff' \
      gds='git diff --staged' \
      gdw='git diff --word-diff'

function gdv() {
    git diff -w "$@" | view -
}
compdef _git gdv=git-diff

alias gdup='git diff @{upstream}'

alias gdt='git diff-tree --no-commit-id --name-only -r' \
      gf='git fetch'
# --jobs=<n> was added in git 2.8
alias gfa='git fetch --all --prune --jobs=10' \
      gfo='git fetch origin' \
      gg='git gui citool' \
      gga='git gui citool --amend' \
      ghh='git help' \
      glgg='git log --graph' \
      glgga='git log --graph --decorate --all' \
      glgm='git log --graph --max-count=10' \
      glods='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset" --date=short' \
      glod='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset"' \
      glola='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --all' \
      glols='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --stat' \
      glol='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset"' \
      glo='git log --oneline --decorate' \
      glog='git log --oneline --decorate --graph' \
      gloga='git log --oneline --decorate --graph --all'

# Pretty log messages
function _git_log_prettily() {
    if ! [ -z $1 ]; then
        git log --pretty=$1
    fi
}
compdef _git _git_log_prettily=git-log

alias glp='_git_log_prettily' \
      glg='git log --stat' \
      glgp='git log --stat --patch' \
      gignored='git ls-files -v | grep "^[[:lower:]]"' \
      gfg='git ls-files | grep' \
      gmr='git merge' \
      gmra='git merge --abort' \
      gmrs="git merge --squash" \
      gmrtl='git mergetool --no-prompt' \
      gmrtlvim='git mergetool --no-prompt --tool=vimdiff'

alias gl='git pull' \
      gpr='git pull --rebase' \
      gprv='git pull --rebase -v' \
      gpra='git pull --rebase --autostash' \
      gprav='git pull --rebase --autostash -v'

function ggu() {
    [[ "$#" != 1 ]] && local b="$(current_branch)"
    git pull --rebase origin "${b:=$1}"
}
compdef _git ggu=git-checkout

alias ggpull='git pull origin "$(current_branch)"'

function ggl() {
    if [[ "$#" != 0 ]] && [[ "$#" != 1 ]]; then
        git pull origin "${*}"
    else
        [[ "$#" == 0 ]] && local b="$(current_branch)"
        git pull origin "${b:=$1}"
    fi
}
compdef _git ggl=git-checkout

alias gluc='git pull upstream $(current_branch)' \
      gp='git push' \
      gpd='git push --dry-run'

function ggf() {
    [[ "$#" != 1 ]] && local b="$(current_branch)"
    git push --force origin "${b:=$1}"
}
compdef _git ggf=git-checkout

alias gpf!='git push --force' \
      gpf='git push --force-with-lease --force-if-includes'

function ggfl() {
    [[ "$#" != 1 ]] && local b="$(current_branch)"
    git push --force-with-lease origin "${b:=$1}"
}
compdef _git ggfl=git-checkout

alias gpsup='git push --set-upstream origin $(current_branch)' \
      gpsupf='git push --set-upstream origin $(current_branch) --force-with-lease --force-if-includes' \
      gpv='git push --verbose' \
      gpoat='git push origin --all && git push origin --tags' \
      gpod='git push origin --delete' \
      ggpush='git push origin "$(current_branch)"' \
      gpu='git push upstream' \
      grb='git rebase' \
      grba='git rebase --abort' \
      grbc='git rebase --continue' \
      grbi='git rebase --interactive' \
      grbo='git rebase --onto' \
      grbs='git rebase --skip' \
      gr='git remote' \
      grv='git remote --verbose' \
      gra='git remote add' \
      grrm='git remote remove' \
      grmv='git remote rename' \
      grset='git remote set-url' \
      grup='git remote update' \
      grh='git reset' \
      gru='git reset --' \
      grhh='git reset --hard' \
      grhk='git reset --keep' \
      grhs='git reset --soft' \
      gpristine='git reset --hard && git clean --force -dfx' \
      groh='git reset origin/$(current_branch) --hard' \
      grs='git restore' \
      grss='git restore --source' \
      grst='git restore --staged' \
      grev='git revert' \
      grm='git rm' \
      grmc='git rm --cached' \
      grt='cd "$(git rev-parse --show-toplevel || echo .)"' \
      gcount='git shortlog --summary --numbered' \
      gsh='git show' \
      gsps='git show --pretty=short --show-signature' \
      gstall='git stash --all' \
      gstaa='git stash apply' \
      gstc='git stash clear' \
      gstd='git stash drop' \
      gstl='git stash list' \
      gstp='git stash pop' \
      gsta='git stash push' \
      gsts='git stash show --patch' \
      gst='git status' \
      gss='git status --short' \
      gsb='git status --short --branch' \
      gsi='git submodule init' \
      gsu='git submodule update' \
      gsw='git switch' \
      gswc='git switch --create' \
      gta='git tag --annotate' \
      gts='git tag --sign' \
      gtv='git tag | sort -V' \
      gignore='git update-index --assume-unchanged' \
      gunignore='git update-index --no-assume-unchanged' \
      gwch='git whatchanged -p --abbrev-commit --pretty=medium' \
      gwt='git worktree' \
      gwta='git worktree add' \
      gwtls='git worktree list' \
      gwtmv='git worktree move' \
      gwtrm='git worktree remove' \
      gstu='gsta --include-untracked' \
      gtl='gtl(){ git tag --sort=-v:refname -n --list "${1}*" }; noglob gtl'
