Git completion script. To be placed in the home directory.
#!bash | |
# | |
# bash completion support for core Git. | |
# | |
# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org> | |
# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/). | |
# Distributed under the GNU General Public License, version 2.0. | |
# | |
# The contained completion routines provide support for completing: | |
# | |
# *) local and remote branch names | |
# *) local and remote tag names | |
# *) .git/remotes file names | |
# *) git 'subcommands' | |
# *) tree paths within 'ref:path/to/file' expressions | |
# *) common --long-options | |
# | |
# To use these routines: | |
# | |
# 1) Copy this file to somewhere (e.g. ~/.git-completion.sh). | |
# 2) Added the following line to your .bashrc: | |
# source ~/.git-completion.sh | |
# | |
# 3) Consider changing your PS1 to also show the current branch: | |
# PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' | |
# | |
# The argument to __git_ps1 will be displayed only if you | |
# are currently in a git repository. The %s token will be | |
# the name of the current branch. | |
# | |
# In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty | |
# value, unstaged (*) and staged (+) changes will be shown next | |
# to the branch name. You can configure this per-repository | |
# with the bash.showDirtyState variable, which defaults to true | |
# once GIT_PS1_SHOWDIRTYSTATE is enabled. | |
# | |
# You can also see if currently something is stashed, by setting | |
# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed, | |
# then a '$' will be shown next to the branch name. | |
# | |
# If you would like to see if there're untracked files, then you can | |
# set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're | |
# untracked files, then a '%' will be shown next to the branch name. | |
# | |
# If you would like to see the difference between HEAD and its | |
# upstream, set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates | |
# you are behind, ">" indicates you are ahead, and "<>" | |
# indicates you have diverged. You can further control | |
# behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated | |
# list of values: | |
# verbose show number of commits ahead/behind (+/-) upstream | |
# legacy don't use the '--count' option available in recent | |
# versions of git-rev-list | |
# git always compare HEAD to @{upstream} | |
# svn always compare HEAD to your SVN upstream | |
# By default, __git_ps1 will compare HEAD to your SVN upstream | |
# if it can find one, or @{upstream} otherwise. Once you have | |
# set GIT_PS1_SHOWUPSTREAM, you can override it on a | |
# per-repository basis by setting the bash.showUpstream config | |
# variable. | |
# | |
# | |
# To submit patches: | |
# | |
# *) Read Documentation/SubmittingPatches | |
# *) Send all patches to the current maintainer: | |
# | |
# "Shawn O. Pearce" <spearce@spearce.org> | |
# | |
# *) Always CC the Git mailing list: | |
# | |
# git@vger.kernel.org | |
# | |
case "$COMP_WORDBREAKS" in | |
*:*) : great ;; | |
*) COMP_WORDBREAKS="$COMP_WORDBREAKS:" | |
esac | |
# __gitdir accepts 0 or 1 arguments (i.e., location) | |
# returns location of .git repo | |
__gitdir () | |
{ | |
if [ -z "${1-}" ]; then | |
if [ -n "${__git_dir-}" ]; then | |
echo "$__git_dir" | |
elif [ -d .git ]; then | |
echo .git | |
else | |
git rev-parse --git-dir 2>/dev/null | |
fi | |
elif [ -d "$1/.git" ]; then | |
echo "$1/.git" | |
else | |
echo "$1" | |
fi | |
} | |
# stores the divergence from upstream in $p | |
# used by GIT_PS1_SHOWUPSTREAM | |
__git_ps1_show_upstream () | |
{ | |
local key value | |
local svn_remote=() svn_url_pattern count n | |
local upstream=git legacy="" verbose="" | |
# get some config options from git-config | |
while read key value; do | |
case "$key" in | |
bash.showupstream) | |
GIT_PS1_SHOWUPSTREAM="$value" | |
if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then | |
p="" | |
return | |
fi | |
;; | |
svn-remote.*.url) | |
svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value" | |
svn_url_pattern+="\\|$value" | |
upstream=svn+git # default upstream is SVN if available, else git | |
;; | |
esac | |
done < <(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ') | |
# parse configuration values | |
for option in ${GIT_PS1_SHOWUPSTREAM}; do | |
case "$option" in | |
git|svn) upstream="$option" ;; | |
verbose) verbose=1 ;; | |
legacy) legacy=1 ;; | |
esac | |
done | |
# Find our upstream | |
case "$upstream" in | |
git) upstream="@{upstream}" ;; | |
svn*) | |
# get the upstream from the "git-svn-id: ..." in a commit message | |
# (git-svn uses essentially the same procedure internally) | |
local svn_upstream=($(git log --first-parent -1 \ | |
--grep="^git-svn-id: \(${svn_url_pattern:2}\)" 2>/dev/null)) | |
if [[ 0 -ne ${#svn_upstream[@]} ]]; then | |
svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]} | |
svn_upstream=${svn_upstream%@*} | |
for ((n=1; "$n" <= "${#svn_remote[@]}"; ++n)); do | |
svn_upstream=${svn_upstream#${svn_remote[$n]}} | |
done | |
if [[ -z "$svn_upstream" ]]; then | |
# default branch name for checkouts with no layout: | |
upstream=${GIT_SVN_ID:-git-svn} | |
else | |
upstream=${svn_upstream#/} | |
fi | |
elif [[ "svn+git" = "$upstream" ]]; then | |
upstream="@{upstream}" | |
fi | |
;; | |
esac | |
# Find how many commits we are ahead/behind our upstream | |
if [[ -z "$legacy" ]]; then | |
count="$(git rev-list --count --left-right \ | |
"$upstream"...HEAD 2>/dev/null)" | |
else | |
# produce equivalent output to --count for older versions of git | |
local commits | |
if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)" | |
then | |
local commit behind=0 ahead=0 | |
for commit in $commits | |
do | |
case "$commit" in | |
"<"*) let ++behind | |
;; | |
*) let ++ahead | |
;; | |
esac | |
done | |
count="$behind $ahead" | |
else | |
count="" | |
fi | |
fi | |
# calculate the result | |
if [[ -z "$verbose" ]]; then | |
case "$count" in | |
"") # no upstream | |
p="" ;; | |
"0 0") # equal to upstream | |
p="=" ;; | |
"0 "*) # ahead of upstream | |
p=">" ;; | |
*" 0") # behind upstream | |
p="<" ;; | |
*) # diverged from upstream | |
p="<>" ;; | |
esac | |
else | |
case "$count" in | |
"") # no upstream | |
p="" ;; | |
"0 0") # equal to upstream | |
p=" u=" ;; | |
"0 "*) # ahead of upstream | |
p=" u+${count#0 }" ;; | |
*" 0") # behind upstream | |
p=" u-${count% 0}" ;; | |
*) # diverged from upstream | |
p=" u+${count#* }-${count% *}" ;; | |
esac | |
fi | |
} | |
# __git_ps1 accepts 0 or 1 arguments (i.e., format string) | |
# returns text to add to bash PS1 prompt (includes branch name) | |
__git_ps1 () | |
{ | |
local g="$(__gitdir)" | |
if [ -n "$g" ]; then | |
local r="" | |
local b="" | |
if [ -f "$g/rebase-merge/interactive" ]; then | |
r="|REBASE-i" | |
b="$(cat "$g/rebase-merge/head-name")" | |
elif [ -d "$g/rebase-merge" ]; then | |
r="|REBASE-m" | |
b="$(cat "$g/rebase-merge/head-name")" | |
else | |
if [ -d "$g/rebase-apply" ]; then | |
if [ -f "$g/rebase-apply/rebasing" ]; then | |
r="|REBASE" | |
elif [ -f "$g/rebase-apply/applying" ]; then | |
r="|AM" | |
else | |
r="|AM/REBASE" | |
fi | |
elif [ -f "$g/MERGE_HEAD" ]; then | |
r="|MERGING" | |
elif [ -f "$g/BISECT_LOG" ]; then | |
r="|BISECTING" | |
fi | |
b="$(git symbolic-ref HEAD 2>/dev/null)" || { | |
b="$( | |
case "${GIT_PS1_DESCRIBE_STYLE-}" in | |
(contains) | |
git describe --contains HEAD ;; | |
(branch) | |
git describe --contains --all HEAD ;; | |
(describe) | |
git describe HEAD ;; | |
(* | default) | |
git describe --exact-match HEAD ;; | |
esac 2>/dev/null)" || | |
b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." || | |
b="unknown" | |
b="($b)" | |
} | |
fi | |
local w="" | |
local i="" | |
local s="" | |
local u="" | |
local c="" | |
local p="" | |
if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then | |
if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then | |
c="BARE:" | |
else | |
b="GIT_DIR!" | |
fi | |
elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then | |
if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then | |
if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then | |
git diff --no-ext-diff --quiet --exit-code || w="*" | |
if git rev-parse --quiet --verify HEAD >/dev/null; then | |
git diff-index --cached --quiet HEAD -- || i="+" | |
else | |
i="#" | |
fi | |
fi | |
fi | |
if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then | |
git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$" | |
fi | |
if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then | |
if [ -n "$(git ls-files --others --exclude-standard)" ]; then | |
u="%" | |
fi | |
fi | |
if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then | |
__git_ps1_show_upstream | |
fi | |
fi | |
local f="$w$i$s$u" | |
printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p" | |
fi | |
} | |
# __gitcomp_1 requires 2 arguments | |
__gitcomp_1 () | |
{ | |
local c IFS=' '$'\t'$'\n' | |
for c in $1; do | |
case "$c$2" in | |
--*=*) printf %s$'\n' "$c$2" ;; | |
*.) printf %s$'\n' "$c$2" ;; | |
*) printf %s$'\n' "$c$2 " ;; | |
esac | |
done | |
} | |
# __gitcomp accepts 1, 2, 3, or 4 arguments | |
# generates completion reply with compgen | |
__gitcomp () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
if [ $# -gt 2 ]; then | |
cur="$3" | |
fi | |
case "$cur" in | |
--*=) | |
COMPREPLY=() | |
;; | |
*) | |
local IFS=$'\n' | |
COMPREPLY=($(compgen -P "${2-}" \ | |
-W "$(__gitcomp_1 "${1-}" "${4-}")" \ | |
-- "$cur")) | |
;; | |
esac | |
} | |
# __git_heads accepts 0 or 1 arguments (to pass to __gitdir) | |
__git_heads () | |
{ | |
local cmd i is_hash=y dir="$(__gitdir "${1-}")" | |
if [ -d "$dir" ]; then | |
git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ | |
refs/heads | |
return | |
fi | |
for i in $(git ls-remote "${1-}" 2>/dev/null); do | |
case "$is_hash,$i" in | |
y,*) is_hash=n ;; | |
n,*^{}) is_hash=y ;; | |
n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;; | |
n,*) is_hash=y; echo "$i" ;; | |
esac | |
done | |
} | |
# __git_tags accepts 0 or 1 arguments (to pass to __gitdir) | |
__git_tags () | |
{ | |
local cmd i is_hash=y dir="$(__gitdir "${1-}")" | |
if [ -d "$dir" ]; then | |
git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ | |
refs/tags | |
return | |
fi | |
for i in $(git ls-remote "${1-}" 2>/dev/null); do | |
case "$is_hash,$i" in | |
y,*) is_hash=n ;; | |
n,*^{}) is_hash=y ;; | |
n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;; | |
n,*) is_hash=y; echo "$i" ;; | |
esac | |
done | |
} | |
# __git_refs accepts 0 or 1 arguments (to pass to __gitdir) | |
__git_refs () | |
{ | |
local i is_hash=y dir="$(__gitdir "${1-}")" | |
local cur="${COMP_WORDS[COMP_CWORD]}" format refs | |
if [ -d "$dir" ]; then | |
case "$cur" in | |
refs|refs/*) | |
format="refname" | |
refs="${cur%/*}" | |
;; | |
*) | |
for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do | |
if [ -e "$dir/$i" ]; then echo $i; fi | |
done | |
format="refname:short" | |
refs="refs/tags refs/heads refs/remotes" | |
;; | |
esac | |
git --git-dir="$dir" for-each-ref --format="%($format)" \ | |
$refs | |
return | |
fi | |
for i in $(git ls-remote "$dir" 2>/dev/null); do | |
case "$is_hash,$i" in | |
y,*) is_hash=n ;; | |
n,*^{}) is_hash=y ;; | |
n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;; | |
n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;; | |
n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;; | |
n,*) is_hash=y; echo "$i" ;; | |
esac | |
done | |
} | |
# __git_refs2 requires 1 argument (to pass to __git_refs) | |
__git_refs2 () | |
{ | |
local i | |
for i in $(__git_refs "$1"); do | |
echo "$i:$i" | |
done | |
} | |
# __git_refs_remotes requires 1 argument (to pass to ls-remote) | |
__git_refs_remotes () | |
{ | |
local cmd i is_hash=y | |
for i in $(git ls-remote "$1" 2>/dev/null); do | |
case "$is_hash,$i" in | |
n,refs/heads/*) | |
is_hash=y | |
echo "$i:refs/remotes/$1/${i#refs/heads/}" | |
;; | |
y,*) is_hash=n ;; | |
n,*^{}) is_hash=y ;; | |
n,refs/tags/*) is_hash=y;; | |
n,*) is_hash=y; ;; | |
esac | |
done | |
} | |
__git_remotes () | |
{ | |
local i ngoff IFS=$'\n' d="$(__gitdir)" | |
shopt -q nullglob || ngoff=1 | |
shopt -s nullglob | |
for i in "$d/remotes"/*; do | |
echo ${i#$d/remotes/} | |
done | |
[ "$ngoff" ] && shopt -u nullglob | |
for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do | |
i="${i#remote.}" | |
echo "${i/.url*/}" | |
done | |
} | |
__git_list_merge_strategies () | |
{ | |
git merge -s help 2>&1 | | |
sed -n -e '/[Aa]vailable strategies are: /,/^$/{ | |
s/\.$// | |
s/.*:// | |
s/^[ ]*// | |
s/[ ]*$// | |
p | |
}' | |
} | |
__git_merge_strategies= | |
# 'git merge -s help' (and thus detection of the merge strategy | |
# list) fails, unfortunately, if run outside of any git working | |
# tree. __git_merge_strategies is set to the empty string in | |
# that case, and the detection will be repeated the next time it | |
# is needed. | |
__git_compute_merge_strategies () | |
{ | |
: ${__git_merge_strategies:=$(__git_list_merge_strategies)} | |
} | |
__git_complete_file () | |
{ | |
local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
?*:*) | |
ref="${cur%%:*}" | |
cur="${cur#*:}" | |
case "$cur" in | |
?*/*) | |
pfx="${cur%/*}" | |
cur="${cur##*/}" | |
ls="$ref:$pfx" | |
pfx="$pfx/" | |
;; | |
*) | |
ls="$ref" | |
;; | |
esac | |
case "$COMP_WORDBREAKS" in | |
*:*) : great ;; | |
*) pfx="$ref:$pfx" ;; | |
esac | |
local IFS=$'\n' | |
COMPREPLY=($(compgen -P "$pfx" \ | |
-W "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \ | |
| sed '/^100... blob /{ | |
s,^.* ,, | |
s,$, , | |
} | |
/^120000 blob /{ | |
s,^.* ,, | |
s,$, , | |
} | |
/^040000 tree /{ | |
s,^.* ,, | |
s,$,/, | |
} | |
s/^.* //')" \ | |
-- "$cur")) | |
;; | |
*) | |
__gitcomp "$(__git_refs)" | |
;; | |
esac | |
} | |
__git_complete_revlist () | |
{ | |
local pfx cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
*...*) | |
pfx="${cur%...*}..." | |
cur="${cur#*...}" | |
__gitcomp "$(__git_refs)" "$pfx" "$cur" | |
;; | |
*..*) | |
pfx="${cur%..*}.." | |
cur="${cur#*..}" | |
__gitcomp "$(__git_refs)" "$pfx" "$cur" | |
;; | |
*) | |
__gitcomp "$(__git_refs)" | |
;; | |
esac | |
} | |
__git_complete_remote_or_refspec () | |
{ | |
local cmd="${COMP_WORDS[1]}" | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0 | |
while [ $c -lt $COMP_CWORD ]; do | |
i="${COMP_WORDS[c]}" | |
case "$i" in | |
--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;; | |
--all) | |
case "$cmd" in | |
push) no_complete_refspec=1 ;; | |
fetch) | |
COMPREPLY=() | |
return | |
;; | |
*) ;; | |
esac | |
;; | |
-*) ;; | |
*) remote="$i"; break ;; | |
esac | |
c=$((++c)) | |
done | |
if [ -z "$remote" ]; then | |
__gitcomp "$(__git_remotes)" | |
return | |
fi | |
if [ $no_complete_refspec = 1 ]; then | |
COMPREPLY=() | |
return | |
fi | |
[ "$remote" = "." ] && remote= | |
case "$cur" in | |
*:*) | |
case "$COMP_WORDBREAKS" in | |
*:*) : great ;; | |
*) pfx="${cur%%:*}:" ;; | |
esac | |
cur="${cur#*:}" | |
lhs=0 | |
;; | |
+*) | |
pfx="+" | |
cur="${cur#+}" | |
;; | |
esac | |
case "$cmd" in | |
fetch) | |
if [ $lhs = 1 ]; then | |
__gitcomp "$(__git_refs2 "$remote")" "$pfx" "$cur" | |
else | |
__gitcomp "$(__git_refs)" "$pfx" "$cur" | |
fi | |
;; | |
pull) | |
if [ $lhs = 1 ]; then | |
__gitcomp "$(__git_refs "$remote")" "$pfx" "$cur" | |
else | |
__gitcomp "$(__git_refs)" "$pfx" "$cur" | |
fi | |
;; | |
push) | |
if [ $lhs = 1 ]; then | |
__gitcomp "$(__git_refs)" "$pfx" "$cur" | |
else | |
__gitcomp "$(__git_refs "$remote")" "$pfx" "$cur" | |
fi | |
;; | |
esac | |
} | |
__git_complete_strategy () | |
{ | |
__git_compute_merge_strategies | |
case "${COMP_WORDS[COMP_CWORD-1]}" in | |
-s|--strategy) | |
__gitcomp "$__git_merge_strategies" | |
return 0 | |
esac | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--strategy=*) | |
__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}" | |
return 0 | |
;; | |
esac | |
return 1 | |
} | |
__git_list_all_commands () | |
{ | |
local i IFS=" "$'\n' | |
for i in $(git help -a|egrep '^ [a-zA-Z0-9]') | |
do | |
case $i in | |
*--*) : helper pattern;; | |
*) echo $i;; | |
esac | |
done | |
} | |
__git_all_commands= | |
__git_compute_all_commands () | |
{ | |
: ${__git_all_commands:=$(__git_list_all_commands)} | |
} | |
__git_list_porcelain_commands () | |
{ | |
local i IFS=" "$'\n' | |
__git_compute_all_commands | |
for i in "help" $__git_all_commands | |
do | |
case $i in | |
*--*) : helper pattern;; | |
applymbox) : ask gittus;; | |
applypatch) : ask gittus;; | |
archimport) : import;; | |
cat-file) : plumbing;; | |
check-attr) : plumbing;; | |
check-ref-format) : plumbing;; | |
checkout-index) : plumbing;; | |
commit-tree) : plumbing;; | |
count-objects) : infrequent;; | |
cvsexportcommit) : export;; | |
cvsimport) : import;; | |
cvsserver) : daemon;; | |
daemon) : daemon;; | |
diff-files) : plumbing;; | |
diff-index) : plumbing;; | |
diff-tree) : plumbing;; | |
fast-import) : import;; | |
fast-export) : export;; | |
fsck-objects) : plumbing;; | |
fetch-pack) : plumbing;; | |
fmt-merge-msg) : plumbing;; | |
for-each-ref) : plumbing;; | |
hash-object) : plumbing;; | |
http-*) : transport;; | |
index-pack) : plumbing;; | |
init-db) : deprecated;; | |
local-fetch) : plumbing;; | |
lost-found) : infrequent;; | |
ls-files) : plumbing;; | |
ls-remote) : plumbing;; | |
ls-tree) : plumbing;; | |
mailinfo) : plumbing;; | |
mailsplit) : plumbing;; | |
merge-*) : plumbing;; | |
mktree) : plumbing;; | |
mktag) : plumbing;; | |
pack-objects) : plumbing;; | |
pack-redundant) : plumbing;; | |
pack-refs) : plumbing;; | |
parse-remote) : plumbing;; | |
patch-id) : plumbing;; | |
peek-remote) : plumbing;; | |
prune) : plumbing;; | |
prune-packed) : plumbing;; | |
quiltimport) : import;; | |
read-tree) : plumbing;; | |
receive-pack) : plumbing;; | |
reflog) : plumbing;; | |
remote-*) : transport;; | |
repo-config) : deprecated;; | |
rerere) : plumbing;; | |
rev-list) : plumbing;; | |
rev-parse) : plumbing;; | |
runstatus) : plumbing;; | |
sh-setup) : internal;; | |
shell) : daemon;; | |
show-ref) : plumbing;; | |
send-pack) : plumbing;; | |
show-index) : plumbing;; | |
ssh-*) : transport;; | |
stripspace) : plumbing;; | |
symbolic-ref) : plumbing;; | |
tar-tree) : deprecated;; | |
unpack-file) : plumbing;; | |
unpack-objects) : plumbing;; | |
update-index) : plumbing;; | |
update-ref) : plumbing;; | |
update-server-info) : daemon;; | |
upload-archive) : plumbing;; | |
upload-pack) : plumbing;; | |
write-tree) : plumbing;; | |
var) : infrequent;; | |
verify-pack) : infrequent;; | |
verify-tag) : plumbing;; | |
*) echo $i;; | |
esac | |
done | |
} | |
__git_porcelain_commands= | |
__git_compute_porcelain_commands () | |
{ | |
__git_compute_all_commands | |
: ${__git_porcelain_commands:=$(__git_list_porcelain_commands)} | |
} | |
__git_aliases () | |
{ | |
local i IFS=$'\n' | |
for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do | |
case "$i" in | |
alias.*) | |
i="${i#alias.}" | |
echo "${i/ */}" | |
;; | |
esac | |
done | |
} | |
# __git_aliased_command requires 1 argument | |
__git_aliased_command () | |
{ | |
local word cmdline=$(git --git-dir="$(__gitdir)" \ | |
config --get "alias.$1") | |
for word in $cmdline; do | |
case "$word" in | |
\!gitk|gitk) | |
echo "gitk" | |
return | |
;; | |
\!*) : shell command alias ;; | |
-*) : option ;; | |
*=*) : setting env ;; | |
git) : git itself ;; | |
*) | |
echo "$word" | |
return | |
esac | |
done | |
} | |
# __git_find_on_cmdline requires 1 argument | |
__git_find_on_cmdline () | |
{ | |
local word subcommand c=1 | |
while [ $c -lt $COMP_CWORD ]; do | |
word="${COMP_WORDS[c]}" | |
for subcommand in $1; do | |
if [ "$subcommand" = "$word" ]; then | |
echo "$subcommand" | |
return | |
fi | |
done | |
c=$((++c)) | |
done | |
} | |
__git_has_doubledash () | |
{ | |
local c=1 | |
while [ $c -lt $COMP_CWORD ]; do | |
if [ "--" = "${COMP_WORDS[c]}" ]; then | |
return 0 | |
fi | |
c=$((++c)) | |
done | |
return 1 | |
} | |
__git_whitespacelist="nowarn warn error error-all fix" | |
_git_am () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)" | |
if [ -d "$dir"/rebase-apply ]; then | |
__gitcomp "--skip --continue --resolved --abort" | |
return | |
fi | |
case "$cur" in | |
--whitespace=*) | |
__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" | |
return | |
;; | |
--*) | |
__gitcomp " | |
--3way --committer-date-is-author-date --ignore-date | |
--ignore-whitespace --ignore-space-change | |
--interactive --keep --no-utf8 --signoff --utf8 | |
--whitespace= --scissors | |
" | |
return | |
esac | |
COMPREPLY=() | |
} | |
_git_apply () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--whitespace=*) | |
__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" | |
return | |
;; | |
--*) | |
__gitcomp " | |
--stat --numstat --summary --check --index | |
--cached --index-info --reverse --reject --unidiff-zero | |
--apply --no-add --exclude= | |
--ignore-whitespace --ignore-space-change | |
--whitespace= --inaccurate-eof --verbose | |
" | |
return | |
esac | |
COMPREPLY=() | |
} | |
_git_add () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp " | |
--interactive --refresh --patch --update --dry-run | |
--ignore-errors --intent-to-add | |
" | |
return | |
esac | |
COMPREPLY=() | |
} | |
_git_archive () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--format=*) | |
__gitcomp "$(git archive --list)" "" "${cur##--format=}" | |
return | |
;; | |
--remote=*) | |
__gitcomp "$(__git_remotes)" "" "${cur##--remote=}" | |
return | |
;; | |
--*) | |
__gitcomp " | |
--format= --list --verbose | |
--prefix= --remote= --exec= | |
" | |
return | |
;; | |
esac | |
__git_complete_file | |
} | |
_git_bisect () | |
{ | |
__git_has_doubledash && return | |
local subcommands="start bad good skip reset visualize replay log run" | |
local subcommand="$(__git_find_on_cmdline "$subcommands")" | |
if [ -z "$subcommand" ]; then | |
__gitcomp "$subcommands" | |
return | |
fi | |
case "$subcommand" in | |
bad|good|reset|skip) | |
__gitcomp "$(__git_refs)" | |
;; | |
*) | |
COMPREPLY=() | |
;; | |
esac | |
} | |
_git_branch () | |
{ | |
local i c=1 only_local_ref="n" has_r="n" | |
while [ $c -lt $COMP_CWORD ]; do | |
i="${COMP_WORDS[c]}" | |
case "$i" in | |
-d|-m) only_local_ref="y" ;; | |
-r) has_r="y" ;; | |
esac | |
c=$((++c)) | |
done | |
case "${COMP_WORDS[COMP_CWORD]}" in | |
--*) | |
__gitcomp " | |
--color --no-color --verbose --abbrev= --no-abbrev | |
--track --no-track --contains --merged --no-merged | |
--set-upstream | |
" | |
;; | |
*) | |
if [ $only_local_ref = "y" -a $has_r = "n" ]; then | |
__gitcomp "$(__git_heads)" | |
else | |
__gitcomp "$(__git_refs)" | |
fi | |
;; | |
esac | |
} | |
_git_bundle () | |
{ | |
local cmd="${COMP_WORDS[2]}" | |
case "$COMP_CWORD" in | |
2) | |
__gitcomp "create list-heads verify unbundle" | |
;; | |
3) | |
# looking for a file | |
;; | |
*) | |
case "$cmd" in | |
create) | |
__git_complete_revlist | |
;; | |
esac | |
;; | |
esac | |
} | |
_git_checkout () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--conflict=*) | |
__gitcomp "diff3 merge" "" "${cur##--conflict=}" | |
;; | |
--*) | |
__gitcomp " | |
--quiet --ours --theirs --track --no-track --merge | |
--conflict= --orphan --patch | |
" | |
;; | |
*) | |
__gitcomp "$(__git_refs)" | |
;; | |
esac | |
} | |
_git_cherry () | |
{ | |
__gitcomp "$(__git_refs)" | |
} | |
_git_cherry_pick () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--edit --no-commit" | |
;; | |
*) | |
__gitcomp "$(__git_refs)" | |
;; | |
esac | |
} | |
_git_clean () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--dry-run --quiet" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_clone () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp " | |
--local | |
--no-hardlinks | |
--shared | |
--reference | |
--quiet | |
--no-checkout | |
--bare | |
--mirror | |
--origin | |
--upload-pack | |
--template= | |
--depth | |
" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_commit () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--cleanup=*) | |
__gitcomp "default strip verbatim whitespace | |
" "" "${cur##--cleanup=}" | |
return | |
;; | |
--reuse-message=*) | |
__gitcomp "$(__git_refs)" "" "${cur##--reuse-message=}" | |
return | |
;; | |
--reedit-message=*) | |
__gitcomp "$(__git_refs)" "" "${cur##--reedit-message=}" | |
return | |
;; | |
--untracked-files=*) | |
__gitcomp "all no normal" "" "${cur##--untracked-files=}" | |
return | |
;; | |
--*) | |
__gitcomp " | |
--all --author= --signoff --verify --no-verify | |
--edit --amend --include --only --interactive | |
--dry-run --reuse-message= --reedit-message= | |
--reset-author --file= --message= --template= | |
--cleanup= --untracked-files --untracked-files= | |
--verbose --quiet | |
" | |
return | |
esac | |
COMPREPLY=() | |
} | |
_git_describe () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp " | |
--all --tags --contains --abbrev= --candidates= | |
--exact-match --debug --long --match --always | |
" | |
return | |
esac | |
__gitcomp "$(__git_refs)" | |
} | |
__git_diff_common_options="--stat --numstat --shortstat --summary | |
--patch-with-stat --name-only --name-status --color | |
--no-color --color-words --no-renames --check | |
--full-index --binary --abbrev --diff-filter= | |
--find-copies-harder | |
--text --ignore-space-at-eol --ignore-space-change | |
--ignore-all-space --exit-code --quiet --ext-diff | |
--no-ext-diff | |
--no-prefix --src-prefix= --dst-prefix= | |
--inter-hunk-context= | |
--patience | |
--raw | |
--dirstat --dirstat= --dirstat-by-file | |
--dirstat-by-file= --cumulative | |
" | |
_git_diff () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex | |
--base --ours --theirs --no-index | |
$__git_diff_common_options | |
" | |
return | |
;; | |
esac | |
__git_complete_file | |
} | |
__git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff | |
tkdiff vimdiff gvimdiff xxdiff araxis p4merge | |
" | |
_git_difftool () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--tool=*) | |
__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}" | |
return | |
;; | |
--*) | |
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex | |
--base --ours --theirs | |
--no-renames --diff-filter= --find-copies-harder | |
--relative --ignore-submodules | |
--tool=" | |
return | |
;; | |
esac | |
__git_complete_file | |
} | |
__git_fetch_options=" | |
--quiet --verbose --append --upload-pack --force --keep --depth= | |
--tags --no-tags --all --prune --dry-run | |
" | |
_git_fetch () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "$__git_fetch_options" | |
return | |
;; | |
esac | |
__git_complete_remote_or_refspec | |
} | |
_git_format_patch () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--thread=*) | |
__gitcomp " | |
deep shallow | |
" "" "${cur##--thread=}" | |
return | |
;; | |
--*) | |
__gitcomp " | |
--stdout --attach --no-attach --thread --thread= | |
--output-directory | |
--numbered --start-number | |
--numbered-files | |
--keep-subject | |
--signoff --signature --no-signature | |
--in-reply-to= --cc= | |
--full-index --binary | |
--not --all | |
--cover-letter | |
--no-prefix --src-prefix= --dst-prefix= | |
--inline --suffix= --ignore-if-in-upstream | |
--subject-prefix= | |
" | |
return | |
;; | |
esac | |
__git_complete_revlist | |
} | |
_git_fsck () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp " | |
--tags --root --unreachable --cache --no-reflogs --full | |
--strict --verbose --lost-found | |
" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_gc () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--prune --aggressive" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_gitk () | |
{ | |
_gitk | |
} | |
_git_grep () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp " | |
--cached | |
--text --ignore-case --word-regexp --invert-match | |
--full-name | |
--extended-regexp --basic-regexp --fixed-strings | |
--files-with-matches --name-only | |
--files-without-match | |
--max-depth | |
--count | |
--and --or --not --all-match | |
" | |
return | |
;; | |
esac | |
__gitcomp "$(__git_refs)" | |
} | |
_git_help () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--all --info --man --web" | |
return | |
;; | |
esac | |
__git_compute_all_commands | |
__gitcomp "$__git_all_commands | |
attributes cli core-tutorial cvs-migration | |
diffcore gitk glossary hooks ignore modules | |
repository-layout tutorial tutorial-2 | |
workflows | |
" | |
} | |
_git_init () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--shared=*) | |
__gitcomp " | |
false true umask group all world everybody | |
" "" "${cur##--shared=}" | |
return | |
;; | |
--*) | |
__gitcomp "--quiet --bare --template= --shared --shared=" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_ls_files () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--cached --deleted --modified --others --ignored | |
--stage --directory --no-empty-directory --unmerged | |
--killed --exclude= --exclude-from= | |
--exclude-per-directory= --exclude-standard | |
--error-unmatch --with-tree= --full-name | |
--abbrev --ignored --exclude-per-directory | |
" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_ls_remote () | |
{ | |
__gitcomp "$(__git_remotes)" | |
} | |
_git_ls_tree () | |
{ | |
__git_complete_file | |
} | |
# Options that go well for log, shortlog and gitk | |
__git_log_common_options=" | |
--not --all | |
--branches --tags --remotes | |
--first-parent --merges --no-merges | |
--max-count= | |
--max-age= --since= --after= | |
--min-age= --until= --before= | |
" | |
# Options that go well for log and gitk (not shortlog) | |
__git_log_gitk_options=" | |
--dense --sparse --full-history | |
--simplify-merges --simplify-by-decoration | |
--left-right | |
" | |
# Options that go well for log and shortlog (not gitk) | |
__git_log_shortlog_options=" | |
--author= --committer= --grep= | |
--all-match | |
" | |
__git_log_pretty_formats="oneline short medium full fuller email raw format:" | |
__git_log_date_formats="relative iso8601 rfc2822 short local default raw" | |
_git_log () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
local g="$(git rev-parse --git-dir 2>/dev/null)" | |
local merge="" | |
if [ -f "$g/MERGE_HEAD" ]; then | |
merge="--merge" | |
fi | |
case "$cur" in | |
--pretty=*) | |
__gitcomp "$__git_log_pretty_formats | |
" "" "${cur##--pretty=}" | |
return | |
;; | |
--format=*) | |
__gitcomp "$__git_log_pretty_formats | |
" "" "${cur##--format=}" | |
return | |
;; | |
--date=*) | |
__gitcomp "$__git_log_date_formats" "" "${cur##--date=}" | |
return | |
;; | |
--decorate=*) | |
__gitcomp "long short" "" "${cur##--decorate=}" | |
return | |
;; | |
--*) | |
__gitcomp " | |
$__git_log_common_options | |
$__git_log_shortlog_options | |
$__git_log_gitk_options | |
--root --topo-order --date-order --reverse | |
--follow --full-diff | |
--abbrev-commit --abbrev= | |
--relative-date --date= | |
--pretty= --format= --oneline | |
--cherry-pick | |
--graph | |
--decorate --decorate= | |
--walk-reflogs | |
--parents --children | |
$merge | |
$__git_diff_common_options | |
--pickaxe-all --pickaxe-regex | |
" | |
return | |
;; | |
esac | |
__git_complete_revlist | |
} | |
__git_merge_options=" | |
--no-commit --no-stat --log --no-log --squash --strategy | |
--commit --stat --no-squash --ff --no-ff --ff-only | |
" | |
_git_merge () | |
{ | |
__git_complete_strategy && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "$__git_merge_options" | |
return | |
esac | |
__gitcomp "$(__git_refs)" | |
} | |
_git_mergetool () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--tool=*) | |
__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}" | |
return | |
;; | |
--*) | |
__gitcomp "--tool=" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_merge_base () | |
{ | |
__gitcomp "$(__git_refs)" | |
} | |
_git_mv () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--dry-run" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_name_rev () | |
{ | |
__gitcomp "--tags --all --stdin" | |
} | |
_git_notes () | |
{ | |
local subcommands="edit show" | |
if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then | |
__gitcomp "$subcommands" | |
return | |
fi | |
case "${COMP_WORDS[COMP_CWORD-1]}" in | |
-m|-F) | |
COMPREPLY=() | |
;; | |
*) | |
__gitcomp "$(__git_refs)" | |
;; | |
esac | |
} | |
_git_pull () | |
{ | |
__git_complete_strategy && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp " | |
--rebase --no-rebase | |
$__git_merge_options | |
$__git_fetch_options | |
" | |
return | |
;; | |
esac | |
__git_complete_remote_or_refspec | |
} | |
_git_push () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "${COMP_WORDS[COMP_CWORD-1]}" in | |
--repo) | |
__gitcomp "$(__git_remotes)" | |
return | |
esac | |
case "$cur" in | |
--repo=*) | |
__gitcomp "$(__git_remotes)" "" "${cur##--repo=}" | |
return | |
;; | |
--*) | |
__gitcomp " | |
--all --mirror --tags --dry-run --force --verbose | |
--receive-pack= --repo= | |
" | |
return | |
;; | |
esac | |
__git_complete_remote_or_refspec | |
} | |
_git_rebase () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)" | |
if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then | |
__gitcomp "--continue --skip --abort" | |
return | |
fi | |
__git_complete_strategy && return | |
case "$cur" in | |
--whitespace=*) | |
__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" | |
return | |
;; | |
--*) | |
__gitcomp " | |
--onto --merge --strategy --interactive | |
--preserve-merges --stat --no-stat | |
--committer-date-is-author-date --ignore-date | |
--ignore-whitespace --whitespace= | |
--autosquash | |
" | |
return | |
esac | |
__gitcomp "$(__git_refs)" | |
} | |
__git_send_email_confirm_options="always never auto cc compose" | |
__git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all" | |
_git_send_email () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--confirm=*) | |
__gitcomp " | |
$__git_send_email_confirm_options | |
" "" "${cur##--confirm=}" | |
return | |
;; | |
--suppress-cc=*) | |
__gitcomp " | |
$__git_send_email_suppresscc_options | |
" "" "${cur##--suppress-cc=}" | |
return | |
;; | |
--smtp-encryption=*) | |
__gitcomp "ssl tls" "" "${cur##--smtp-encryption=}" | |
return | |
;; | |
--*) | |
__gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to | |
--compose --confirm= --dry-run --envelope-sender | |
--from --identity | |
--in-reply-to --no-chain-reply-to --no-signed-off-by-cc | |
--no-suppress-from --no-thread --quiet | |
--signed-off-by-cc --smtp-pass --smtp-server | |
--smtp-server-port --smtp-encryption= --smtp-user | |
--subject --suppress-cc= --suppress-from --thread --to | |
--validate --no-validate" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_stage () | |
{ | |
_git_add | |
} | |
__git_config_get_set_variables () | |
{ | |
local prevword word config_file= c=$COMP_CWORD | |
while [ $c -gt 1 ]; do | |
word="${COMP_WORDS[c]}" | |
case "$word" in | |
--global|--system|--file=*) | |
config_file="$word" | |
break | |
;; | |
-f|--file) | |
config_file="$word $prevword" | |
break | |
;; | |
esac | |
prevword=$word | |
c=$((--c)) | |
done | |
git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null | | |
while read line | |
do | |
case "$line" in | |
*.*=*) | |
echo "${line/=*/}" | |
;; | |
esac | |
done | |
} | |
_git_config () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
local prv="${COMP_WORDS[COMP_CWORD-1]}" | |
case "$prv" in | |
branch.*.remote) | |
__gitcomp "$(__git_remotes)" | |
return | |
;; | |
branch.*.merge) | |
__gitcomp "$(__git_refs)" | |
return | |
;; | |
remote.*.fetch) | |
local remote="${prv#remote.}" | |
remote="${remote%.fetch}" | |
__gitcomp "$(__git_refs_remotes "$remote")" | |
return | |
;; | |
remote.*.push) | |
local remote="${prv#remote.}" | |
remote="${remote%.push}" | |
__gitcomp "$(git --git-dir="$(__gitdir)" \ | |
for-each-ref --format='%(refname):%(refname)' \ | |
refs/heads)" | |
return | |
;; | |
pull.twohead|pull.octopus) | |
__git_compute_merge_strategies | |
__gitcomp "$__git_merge_strategies" | |
return | |
;; | |
color.branch|color.diff|color.interactive|\ | |
color.showbranch|color.status|color.ui) | |
__gitcomp "always never auto" | |
return | |
;; | |
color.pager) | |
__gitcomp "false true" | |
return | |
;; | |
color.*.*) | |
__gitcomp " | |
normal black red green yellow blue magenta cyan white | |
bold dim ul blink reverse | |
" | |
return | |
;; | |
help.format) | |
__gitcomp "man info web html" | |
return | |
;; | |
log.date) | |
__gitcomp "$__git_log_date_formats" | |
return | |
;; | |
sendemail.aliasesfiletype) | |
__gitcomp "mutt mailrc pine elm gnus" | |
return | |
;; | |
sendemail.confirm) | |
__gitcomp "$__git_send_email_confirm_options" | |
return | |
;; | |
sendemail.suppresscc) | |
__gitcomp "$__git_send_email_suppresscc_options" | |
return | |
;; | |
--get|--get-all|--unset|--unset-all) | |
__gitcomp "$(__git_config_get_set_variables)" | |
return | |
;; | |
*.*) | |
COMPREPLY=() | |
return | |
;; | |
esac | |
case "$cur" in | |
--*) | |
__gitcomp " | |
--global --system --file= | |
--list --replace-all | |
--get --get-all --get-regexp | |
--add --unset --unset-all | |
--remove-section --rename-section | |
" | |
return | |
;; | |
branch.*.*) | |
local pfx="${cur%.*}." | |
cur="${cur##*.}" | |
__gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur" | |
return | |
;; | |
branch.*) | |
local pfx="${cur%.*}." | |
cur="${cur#*.}" | |
__gitcomp "$(__git_heads)" "$pfx" "$cur" "." | |
return | |
;; | |
guitool.*.*) | |
local pfx="${cur%.*}." | |
cur="${cur##*.}" | |
__gitcomp " | |
argprompt cmd confirm needsfile noconsole norescan | |
prompt revprompt revunmerged title | |
" "$pfx" "$cur" | |
return | |
;; | |
difftool.*.*) | |
local pfx="${cur%.*}." | |
cur="${cur##*.}" | |
__gitcomp "cmd path" "$pfx" "$cur" | |
return | |
;; | |
man.*.*) | |
local pfx="${cur%.*}." | |
cur="${cur##*.}" | |
__gitcomp "cmd path" "$pfx" "$cur" | |
return | |
;; | |
mergetool.*.*) | |
local pfx="${cur%.*}." | |
cur="${cur##*.}" | |
__gitcomp "cmd path trustExitCode" "$pfx" "$cur" | |
return | |
;; | |
pager.*) | |
local pfx="${cur%.*}." | |
cur="${cur#*.}" | |
__git_compute_all_commands | |
__gitcomp "$__git_all_commands" "$pfx" "$cur" | |
return | |
;; | |
remote.*.*) | |
local pfx="${cur%.*}." | |
cur="${cur##*.}" | |
__gitcomp " | |
url proxy fetch push mirror skipDefaultUpdate | |
receivepack uploadpack tagopt pushurl | |
" "$pfx" "$cur" | |
return | |
;; | |
remote.*) | |
local pfx="${cur%.*}." | |
cur="${cur#*.}" | |
__gitcomp "$(__git_remotes)" "$pfx" "$cur" "." | |
return | |
;; | |
url.*.*) | |
local pfx="${cur%.*}." | |
cur="${cur##*.}" | |
__gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur" | |
return | |
;; | |
esac | |
__gitcomp " | |
add.ignore-errors | |
alias. | |
apply.ignorewhitespace | |
apply.whitespace | |
branch.autosetupmerge | |
branch.autosetuprebase | |
clean.requireForce | |
color.branch | |
color.branch.current | |
color.branch.local | |
color.branch.plain | |
color.branch.remote | |
color.diff | |
color.diff.commit | |
color.diff.frag | |
color.diff.meta | |
color.diff.new | |
color.diff.old | |
color.diff.plain | |
color.diff.whitespace | |
color.grep | |
color.grep.external | |
color.grep.match | |
color.interactive | |
color.interactive.header | |
color.interactive.help | |
color.interactive.prompt | |
color.pager | |
color.showbranch | |
color.status | |
color.status.added | |
color.status.changed | |
color.status.header | |
color.status.nobranch | |
color.status.untracked | |
color.status.updated | |
color.ui | |
commit.template | |
core.autocrlf | |
core.bare | |
core.compression | |
core.createObject | |
core.deltaBaseCacheLimit | |
core.editor | |
core.excludesfile | |
core.fileMode | |
core.fsyncobjectfiles | |
core.gitProxy | |
core.ignoreCygwinFSTricks | |
core.ignoreStat | |
core.logAllRefUpdates | |
core.loosecompression | |
core.packedGitLimit | |
core.packedGitWindowSize | |
core.pager | |
core.preferSymlinkRefs | |
core.preloadindex | |
core.quotepath | |
core.repositoryFormatVersion | |
core.safecrlf | |
core.sharedRepository | |
core.symlinks | |
core.trustctime | |
core.warnAmbiguousRefs | |
core.whitespace | |
core.worktree | |
diff.autorefreshindex | |
diff.external | |
diff.mnemonicprefix | |
diff.renameLimit | |
diff.renameLimit. | |
diff.renames | |
diff.suppressBlankEmpty | |
diff.tool | |
diff.wordRegex | |
difftool. | |
difftool.prompt | |
fetch.unpackLimit | |
format.attach | |
format.cc | |
format.headers | |
format.numbered | |
format.pretty | |
format.signature | |
format.signoff | |
format.subjectprefix | |
format.suffix | |
format.thread | |
gc.aggressiveWindow | |
gc.auto | |
gc.autopacklimit | |
gc.packrefs | |
gc.pruneexpire | |
gc.reflogexpire | |
gc.reflogexpireunreachable | |
gc.rerereresolved | |
gc.rerereunresolved | |
gitcvs.allbinary | |
gitcvs.commitmsgannotation | |
gitcvs.dbTableNamePrefix | |
gitcvs.dbdriver | |
gitcvs.dbname | |
gitcvs.dbpass | |
gitcvs.dbuser | |
gitcvs.enabled | |
gitcvs.logfile | |
gitcvs.usecrlfattr | |
guitool. | |
gui.blamehistoryctx | |
gui.commitmsgwidth | |
gui.copyblamethreshold | |
gui.diffcontext | |
gui.encoding | |
gui.fastcopyblame | |
gui.matchtrackingbranch | |
gui.newbranchtemplate | |
gui.pruneduringfetch | |
gui.spellingdictionary | |
gui.trustmtime | |
help.autocorrect | |
help.browser | |
help.format | |
http.lowSpeedLimit | |
http.lowSpeedTime | |
http.maxRequests | |
http.noEPSV | |
http.proxy | |
http.sslCAInfo | |
http.sslCAPath | |
http.sslCert | |
http.sslKey | |
http.sslVerify | |
i18n.commitEncoding | |
i18n.logOutputEncoding | |
imap.folder | |
imap.host | |
imap.pass | |
imap.port | |
imap.preformattedHTML | |
imap.sslverify | |
imap.tunnel | |
imap.user | |
instaweb.browser | |
instaweb.httpd | |
instaweb.local | |
instaweb.modulepath | |
instaweb.port | |
interactive.singlekey | |
log.date | |
log.showroot | |
mailmap.file | |
man. | |
man.viewer | |
merge.conflictstyle | |
merge.log | |
merge.renameLimit | |
merge.stat | |
merge.tool | |
merge.verbosity | |
mergetool. | |
mergetool.keepBackup | |
mergetool.prompt | |
pack.compression | |
pack.deltaCacheLimit | |
pack.deltaCacheSize | |
pack.depth | |
pack.indexVersion | |
pack.packSizeLimit | |
pack.threads | |
pack.window | |
pack.windowMemory | |
pager. | |
pull.octopus | |
pull.twohead | |
push.default | |
rebase.stat | |
receive.denyCurrentBranch | |
receive.denyDeletes | |
receive.denyNonFastForwards | |
receive.fsckObjects | |
receive.unpackLimit | |
repack.usedeltabaseoffset | |
rerere.autoupdate | |
rerere.enabled | |
sendemail.aliasesfile | |
sendemail.aliasesfiletype | |
sendemail.bcc | |
sendemail.cc | |
sendemail.cccmd | |
sendemail.chainreplyto | |
sendemail.confirm | |
sendemail.envelopesender | |
sendemail.multiedit | |
sendemail.signedoffbycc | |
sendemail.smtpencryption | |
sendemail.smtppass | |
sendemail.smtpserver | |
sendemail.smtpserverport | |
sendemail.smtpuser | |
sendemail.suppresscc | |
sendemail.suppressfrom | |
sendemail.thread | |
sendemail.to | |
sendemail.validate | |
showbranch.default | |
status.relativePaths | |
status.showUntrackedFiles | |
tar.umask | |
transfer.unpackLimit | |
url. | |
user.email | |
user.name | |
user.signingkey | |
web.browser | |
branch. remote. | |
" | |
} | |
_git_remote () | |
{ | |
local subcommands="add rename rm show prune update set-head" | |
local subcommand="$(__git_find_on_cmdline "$subcommands")" | |
if [ -z "$subcommand" ]; then | |
__gitcomp "$subcommands" | |
return | |
fi | |
case "$subcommand" in | |
rename|rm|show|prune) | |
__gitcomp "$(__git_remotes)" | |
;; | |
update) | |
local i c='' IFS=$'\n' | |
for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do | |
i="${i#remotes.}" | |
c="$c ${i/ */}" | |
done | |
__gitcomp "$c" | |
;; | |
*) | |
COMPREPLY=() | |
;; | |
esac | |
} | |
_git_replace () | |
{ | |
__gitcomp "$(__git_refs)" | |
} | |
_git_reset () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--merge --mixed --hard --soft --patch" | |
return | |
;; | |
esac | |
__gitcomp "$(__git_refs)" | |
} | |
_git_revert () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--edit --mainline --no-edit --no-commit --signoff" | |
return | |
;; | |
esac | |
__gitcomp "$(__git_refs)" | |
} | |
_git_rm () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--cached --dry-run --ignore-unmatch --quiet" | |
return | |
;; | |
esac | |
COMPREPLY=() | |
} | |
_git_shortlog () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp " | |
$__git_log_common_options | |
$__git_log_shortlog_options | |
--numbered --summary | |
" | |
return | |
;; | |
esac | |
__git_complete_revlist | |
} | |
_git_show () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--pretty=*) | |
__gitcomp "$__git_log_pretty_formats | |
" "" "${cur##--pretty=}" | |
return | |
;; | |
--format=*) | |
__gitcomp "$__git_log_pretty_formats | |
" "" "${cur##--format=}" | |
return | |
;; | |
--*) | |
__gitcomp "--pretty= --format= --abbrev-commit --oneline | |
$__git_diff_common_options | |
" | |
return | |
;; | |
esac | |
__git_complete_file | |
} | |
_git_show_branch () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp " | |
--all --remotes --topo-order --current --more= | |
--list --independent --merge-base --no-name | |
--color --no-color | |
--sha1-name --sparse --topics --reflog | |
" | |
return | |
;; | |
esac | |
__git_complete_revlist | |
} | |
_git_stash () | |
{ | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
local save_opts='--keep-index --no-keep-index --quiet --patch' | |
local subcommands='save list show apply clear drop pop create branch' | |
local subcommand="$(__git_find_on_cmdline "$subcommands")" | |
if [ -z "$subcommand" ]; then | |
case "$cur" in | |
--*) | |
__gitcomp "$save_opts" | |
;; | |
*) | |
if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then | |
__gitcomp "$subcommands" | |
else | |
COMPREPLY=() | |
fi | |
;; | |
esac | |
else | |
case "$subcommand,$cur" in | |
save,--*) | |
__gitcomp "$save_opts" | |
;; | |
apply,--*|pop,--*) | |
__gitcomp "--index --quiet" | |
;; | |
show,--*|drop,--*|branch,--*) | |
COMPREPLY=() | |
;; | |
show,*|apply,*|drop,*|pop,*|branch,*) | |
__gitcomp "$(git --git-dir="$(__gitdir)" stash list \ | |
| sed -n -e 's/:.*//p')" | |
;; | |
*) | |
COMPREPLY=() | |
;; | |
esac | |
fi | |
} | |
_git_submodule () | |
{ | |
__git_has_doubledash && return | |
local subcommands="add status init update summary foreach sync" | |
if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$cur" in | |
--*) | |
__gitcomp "--quiet --cached" | |
;; | |
*) | |
__gitcomp "$subcommands" | |
;; | |
esac | |
return | |
fi | |
} | |
_git_svn () | |
{ | |
local subcommands=" | |
init fetch clone rebase dcommit log find-rev | |
set-tree commit-diff info create-ignore propget | |
proplist show-ignore show-externals branch tag blame | |
migrate mkdirs reset gc | |
" | |
local subcommand="$(__git_find_on_cmdline "$subcommands")" | |
if [ -z "$subcommand" ]; then | |
__gitcomp "$subcommands" | |
else | |
local remote_opts="--username= --config-dir= --no-auth-cache" | |
local fc_opts=" | |
--follow-parent --authors-file= --repack= | |
--no-metadata --use-svm-props --use-svnsync-props | |
--log-window-size= --no-checkout --quiet | |
--repack-flags --use-log-author --localtime | |
--ignore-paths= $remote_opts | |
" | |
local init_opts=" | |
--template= --shared= --trunk= --tags= | |
--branches= --stdlayout --minimize-url | |
--no-metadata --use-svm-props --use-svnsync-props | |
--rewrite-root= --prefix= --use-log-author | |
--add-author-from $remote_opts | |
" | |
local cmt_opts=" | |
--edit --rmdir --find-copies-harder --copy-similarity= | |
" | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
case "$subcommand,$cur" in | |
fetch,--*) | |
__gitcomp "--revision= --fetch-all $fc_opts" | |
;; | |
clone,--*) | |
__gitcomp "--revision= $fc_opts $init_opts" | |
;; | |
init,--*) | |
__gitcomp "$init_opts" | |
;; | |
dcommit,--*) | |
__gitcomp " | |
--merge --strategy= --verbose --dry-run | |
--fetch-all --no-rebase --commit-url | |
--revision $cmt_opts $fc_opts | |
" | |
;; | |
set-tree,--*) | |
__gitcomp "--stdin $cmt_opts $fc_opts" | |
;; | |
create-ignore,--*|propget,--*|proplist,--*|show-ignore,--*|\ | |
show-externals,--*|mkdirs,--*) | |
__gitcomp "--revision=" | |
;; | |
log,--*) | |
__gitcomp " | |
--limit= --revision= --verbose --incremental | |
--oneline --show-commit --non-recursive | |
--authors-file= --color | |
" | |
;; | |
rebase,--*) | |
__gitcomp " | |
--merge --verbose --strategy= --local | |
--fetch-all --dry-run $fc_opts | |
" | |
;; | |
commit-diff,--*) | |
__gitcomp "--message= --file= --revision= $cmt_opts" | |
;; | |
info,--*) | |
__gitcomp "--url" | |
;; | |
branch,--*) | |
__gitcomp "--dry-run --message --tag" | |
;; | |
tag,--*) | |
__gitcomp "--dry-run --message" | |
;; | |
blame,--*) | |
__gitcomp "--git-format" | |
;; | |
migrate,--*) | |
__gitcomp " | |
--config-dir= --ignore-paths= --minimize | |
--no-auth-cache --username= | |
" | |
;; | |
reset,--*) | |
__gitcomp "--revision= --parent" | |
;; | |
*) | |
COMPREPLY=() | |
;; | |
esac | |
fi | |
} | |
_git_tag () | |
{ | |
local i c=1 f=0 | |
while [ $c -lt $COMP_CWORD ]; do | |
i="${COMP_WORDS[c]}" | |
case "$i" in | |
-d|-v) | |
__gitcomp "$(__git_tags)" | |
return | |
;; | |
-f) | |
f=1 | |
;; | |
esac | |
c=$((++c)) | |
done | |
case "${COMP_WORDS[COMP_CWORD-1]}" in | |
-m|-F) | |
COMPREPLY=() | |
;; | |
-*|tag) | |
if [ $f = 1 ]; then | |
__gitcomp "$(__git_tags)" | |
else | |
COMPREPLY=() | |
fi | |
;; | |
*) | |
__gitcomp "$(__git_refs)" | |
;; | |
esac | |
} | |
_git_whatchanged () | |
{ | |
_git_log | |
} | |
_git () | |
{ | |
local i c=1 command __git_dir | |
while [ $c -lt $COMP_CWORD ]; do | |
i="${COMP_WORDS[c]}" | |
case "$i" in | |
--git-dir=*) __git_dir="${i#--git-dir=}" ;; | |
--bare) __git_dir="." ;; | |
--version|-p|--paginate) ;; | |
--help) command="help"; break ;; | |
*) command="$i"; break ;; | |
esac | |
c=$((++c)) | |
done | |
if [ -z "$command" ]; then | |
case "${COMP_WORDS[COMP_CWORD]}" in | |
--*) __gitcomp " | |
--paginate | |
--no-pager | |
--git-dir= | |
--bare | |
--version | |
--exec-path | |
--html-path | |
--work-tree= | |
--help | |
" | |
;; | |
*) __git_compute_porcelain_commands | |
__gitcomp "$__git_porcelain_commands $(__git_aliases)" ;; | |
esac | |
return | |
fi | |
local completion_func="_git_${command//-/_}" | |
declare -F $completion_func >/dev/null && $completion_func && return | |
local expansion=$(__git_aliased_command "$command") | |
if [ -n "$expansion" ]; then | |
completion_func="_git_${expansion//-/_}" | |
declare -F $completion_func >/dev/null && $completion_func | |
fi | |
} | |
_gitk () | |
{ | |
__git_has_doubledash && return | |
local cur="${COMP_WORDS[COMP_CWORD]}" | |
local g="$(__gitdir)" | |
local merge="" | |
if [ -f "$g/MERGE_HEAD" ]; then | |
merge="--merge" | |
fi | |
case "$cur" in | |
--*) | |
__gitcomp " | |
$__git_log_common_options | |
$__git_log_gitk_options | |
$merge | |
" | |
return | |
;; | |
esac | |
__git_complete_revlist | |
} | |
complete -o bashdefault -o default -o nospace -F _git git 2>/dev/null \ | |
|| complete -o default -o nospace -F _git git | |
complete -o bashdefault -o default -o nospace -F _gitk gitk 2>/dev/null \ | |
|| complete -o default -o nospace -F _gitk gitk | |
# The following are necessary only for Cygwin, and only are needed | |
# when the user has tab-completed the executable name and consequently | |
# included the '.exe' suffix. | |
# | |
if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then | |
complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \ | |
|| complete -o default -o nospace -F _git git.exe | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment