Merge branch 'nd/ignore-might-be-precious'
[gitweb.git] / contrib / completion / git-completion.bash
index 93800601f8f337eb420d97f5d5b74744a0c0609d..cc1bdf960949cfeb977d8a188a2324b48bf5c6df 100755 (executable)
@@ -1,6 +1,6 @@
 #!bash
 #
-# bash completion support for core Git.
+# bash/zsh completion support for core Git.
 #
 # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
 # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
 # 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
-#
-#       Or, add the following lines to your .zshrc:
-#        autoload bashcompinit
-#        bashcompinit
+#    2) Add the following line to your .bashrc/.zshrc:
 #        source ~/.git-completion.sh
 #
 #    3) Consider changing your PS1 to also show the current branch:
-#        PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+#         Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+#         ZSH:  PS1='[%n@%m %c$(__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
 #       git@vger.kernel.org
 #
 
+if [[ -n ${ZSH_VERSION-} ]]; then
+       autoload -U +X bashcompinit && bashcompinit
+fi
+
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
 *)   COMP_WORDBREAKS="$COMP_WORDBREAKS:"
@@ -110,6 +110,7 @@ __git_ps1_show_upstream ()
        local upstream=git legacy="" verbose=""
 
        # get some config options from git-config
+       local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
        while read key value; do
                case "$key" in
                bash.showupstream)
@@ -125,7 +126,7 @@ __git_ps1_show_upstream ()
                        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 ')
+       done <<< "$output"
 
        # parse configuration values
        for option in ${GIT_PS1_SHOWUPSTREAM}; do
@@ -485,16 +486,21 @@ _get_comp_words_by_ref ()
 fi
 fi
 
-# __gitcomp accepts 1, 2, 3, or 4 arguments
-# generates completion reply with compgen
+# Generates completion reply with compgen, appending a space to possible
+# completion words, if necessary.
+# It accepts 1 to 4 arguments:
+# 1: List of possible completion words.
+# 2: A prefix to be added to each possible completion word (optional).
+# 3: Generate possible completion matches for this word (optional).
+# 4: A suffix to be appended to each possible completion word (optional).
 __gitcomp ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
+       local cur_="$cur"
+
        if [ $# -gt 2 ]; then
-               cur="$3"
+               cur_="$3"
        fi
-       case "$cur" in
+       case "$cur_" in
        --*=)
                COMPREPLY=()
                ;;
@@ -502,47 +508,54 @@ __gitcomp ()
                local IFS=$'\n'
                COMPREPLY=($(compgen -P "${2-}" \
                        -W "$(__gitcomp_1 "${1-}" "${4-}")" \
-                       -- "$cur"))
+                       -- "$cur_"))
                ;;
        esac
 }
 
-# __git_heads accepts 0 or 1 arguments (to pass to __gitdir)
+# Generates completion reply with compgen from newline-separated possible
+# completion words by appending a space to all of them.
+# It accepts 1 to 4 arguments:
+# 1: List of possible completion words, separated by a single newline.
+# 2: A prefix to be added to each possible completion word (optional).
+# 3: Generate possible completion matches for this word (optional).
+# 4: A suffix to be appended to each possible completion word instead of
+#    the default space (optional).  If specified but empty, nothing is
+#    appended.
+__gitcomp_nl ()
+{
+       local s=$'\n' IFS=' '$'\t'$'\n'
+       local cur_="$cur" suffix=" "
+
+       if [ $# -gt 2 ]; then
+               cur_="$3"
+               if [ $# -gt 3 ]; then
+                       suffix="$4"
+               fi
+       fi
+
+       IFS=$s
+       COMPREPLY=($(compgen -P "${2-}" -S "$suffix" -W "$1" -- "$cur_"))
+}
+
 __git_heads ()
 {
-       local cmd i is_hash=y dir="$(__gitdir "${1-}")"
+       local dir="$(__gitdir)"
        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-}")"
+       local dir="$(__gitdir)"
        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, 1 (to pass to __gitdir), or 2 arguments
@@ -550,9 +563,8 @@ __git_tags ()
 # by checkout for tracking branches
 __git_refs ()
 {
-       local i is_hash=y dir="$(__gitdir "${1-}")" track="${2-}"
-       local cur format refs
-       _get_comp_words_by_ref -n =: cur
+       local i hash dir="$(__gitdir "${1-}")" track="${2-}"
+       local format refs
        if [ -d "$dir" ]; then
                case "$cur" in
                refs|refs/*)
@@ -587,16 +599,27 @@ __git_refs ()
                fi
                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
+       case "$cur" in
+       refs|refs/*)
+               git ls-remote "$dir" "$cur*" 2>/dev/null | \
+               while read hash i; do
+                       case "$i" in
+                       *^{}) ;;
+                       *) echo "$i" ;;
+                       esac
+               done
+               ;;
+       *)
+               git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \
+               while read hash i; do
+                       case "$i" in
+                       *^{}) ;;
+                       refs/*) echo "${i#refs/*/}" ;;
+                       *) echo "$i" ;;
+                       esac
+               done
+               ;;
+       esac
 }
 
 # __git_refs2 requires 1 argument (to pass to __git_refs)
@@ -611,30 +634,22 @@ __git_refs2 ()
 # __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
+       local i hash
+       git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \
+       while read hash i; do
+               echo "$i:refs/remotes/$1/${i#refs/heads/}"
        done
 }
 
 __git_remotes ()
 {
        local i ngoff IFS=$'\n' d="$(__gitdir)"
-       shopt -q nullglob || ngoff=1
-       shopt -s nullglob
+       __git_shopt -q nullglob || ngoff=1
+       __git_shopt -s nullglob
        for i in "$d/remotes"/*; do
                echo ${i#$d/remotes/}
        done
-       [ "$ngoff" ] && shopt -u nullglob
+       [ "$ngoff" ] && __git_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*/}"
@@ -666,19 +681,18 @@ __git_compute_merge_strategies ()
 
 __git_complete_revlist_file ()
 {
-       local pfx ls ref cur
-       _get_comp_words_by_ref -n =: cur
-       case "$cur" in
+       local pfx ls ref cur_="$cur"
+       case "$cur_" in
        *..?*:*)
                return
                ;;
        ?*:*)
-               ref="${cur%%:*}"
-               cur="${cur#*:}"
-               case "$cur" in
+               ref="${cur_%%:*}"
+               cur_="${cur_#*:}"
+               case "$cur_" in
                ?*/*)
-                       pfx="${cur%/*}"
-                       cur="${cur##*/}"
+                       pfx="${cur_%/*}"
+                       cur_="${cur_##*/}"
                        ls="$ref:$pfx"
                        pfx="$pfx/"
                        ;;
@@ -708,20 +722,20 @@ __git_complete_revlist_file ()
                                           s,$,/,
                                       }
                                       s/^.*    //')" \
-                       -- "$cur"))
+                       -- "$cur_"))
                ;;
        *...*)
-               pfx="${cur%...*}..."
-               cur="${cur#*...}"
-               __gitcomp "$(__git_refs)" "$pfx" "$cur"
+               pfx="${cur_%...*}..."
+               cur_="${cur_#*...}"
+               __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
                ;;
        *..*)
-               pfx="${cur%..*}.."
-               cur="${cur#*..}"
-               __gitcomp "$(__git_refs)" "$pfx" "$cur"
+               pfx="${cur_%..*}.."
+               cur_="${cur_#*..}"
+               __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
                ;;
        *)
-               __gitcomp "$(__git_refs)"
+               __gitcomp_nl "$(__git_refs)"
                ;;
        esac
 }
@@ -739,9 +753,7 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-       local cur words cword
-       _get_comp_words_by_ref -n =: cur words cword
-       local cmd="${words[1]}"
+       local cur_="$cur" cmd="${words[1]}"
        local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
        while [ $c -lt $cword ]; do
                i="${words[c]}"
@@ -763,7 +775,7 @@ __git_complete_remote_or_refspec ()
                c=$((++c))
        done
        if [ -z "$remote" ]; then
-               __gitcomp "$(__git_remotes)"
+               __gitcomp_nl "$(__git_remotes)"
                return
        fi
        if [ $no_complete_refspec = 1 ]; then
@@ -771,40 +783,40 @@ __git_complete_remote_or_refspec ()
                return
        fi
        [ "$remote" = "." ] && remote=
-       case "$cur" in
+       case "$cur_" in
        *:*)
                case "$COMP_WORDBREAKS" in
                *:*) : great ;;
-               *)   pfx="${cur%%:*}:" ;;
+               *)   pfx="${cur_%%:*}:" ;;
                esac
-               cur="${cur#*:}"
+               cur_="${cur_#*:}"
                lhs=0
                ;;
        +*)
                pfx="+"
-               cur="${cur#+}"
+               cur_="${cur_#+}"
                ;;
        esac
        case "$cmd" in
        fetch)
                if [ $lhs = 1 ]; then
-                       __gitcomp "$(__git_refs2 "$remote")" "$pfx" "$cur"
+                       __gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_"
                else
-                       __gitcomp "$(__git_refs)" "$pfx" "$cur"
+                       __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
                fi
                ;;
        pull)
                if [ $lhs = 1 ]; then
-                       __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
+                       __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
                else
-                       __gitcomp "$(__git_refs)" "$pfx" "$cur"
+                       __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
                fi
                ;;
        push)
                if [ $lhs = 1 ]; then
-                       __gitcomp "$(__git_refs)" "$pfx" "$cur"
+                       __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
                else
-                       __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
+                       __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
                fi
                ;;
        esac
@@ -812,8 +824,6 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
-       local cur prev
-       _get_comp_words_by_ref -n =: cur prev
        __git_compute_merge_strategies
        case "$prev" in
        -s|--strategy)
@@ -991,8 +1001,7 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-       local word subcommand c=1 words cword
-       _get_comp_words_by_ref -n =: words cword
+       local word subcommand c=1
        while [ $c -lt $cword ]; do
                word="${words[c]}"
                for subcommand in $1; do
@@ -1007,8 +1016,7 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-       local c=1 words cword
-       _get_comp_words_by_ref -n =: words cword
+       local c=1
        while [ $c -lt $cword ]; do
                if [ "--" = "${words[c]}" ]; then
                        return 0
@@ -1022,8 +1030,7 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-       local cur dir="$(__gitdir)"
-       _get_comp_words_by_ref -n =: cur
+       local dir="$(__gitdir)"
        if [ -d "$dir"/rebase-apply ]; then
                __gitcomp "--skip --continue --resolved --abort"
                return
@@ -1047,8 +1054,6 @@ _git_am ()
 
 _git_apply ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --whitespace=*)
                __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -1071,8 +1076,6 @@ _git_add ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
@@ -1086,15 +1089,13 @@ _git_add ()
 
 _git_archive ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --format=*)
                __gitcomp "$(git archive --list)" "" "${cur##--format=}"
                return
                ;;
        --remote=*)
-               __gitcomp "$(__git_remotes)" "" "${cur##--remote=}"
+               __gitcomp_nl "$(__git_remotes)" "" "${cur##--remote=}"
                return
                ;;
        --*)
@@ -1125,7 +1126,7 @@ _git_bisect ()
 
        case "$subcommand" in
        bad|good|reset|skip|start)
-               __gitcomp "$(__git_refs)"
+               __gitcomp_nl "$(__git_refs)"
                ;;
        *)
                COMPREPLY=()
@@ -1135,9 +1136,8 @@ _git_bisect ()
 
 _git_branch ()
 {
-       local i c=1 only_local_ref="n" has_r="n" cur words cword
+       local i c=1 only_local_ref="n" has_r="n"
 
-       _get_comp_words_by_ref -n =: cur words cword
        while [ $c -lt $cword ]; do
                i="${words[c]}"
                case "$i" in
@@ -1157,9 +1157,9 @@ _git_branch ()
                ;;
        *)
                if [ $only_local_ref = "y" -a $has_r = "n" ]; then
-                       __gitcomp "$(__git_heads)"
+                       __gitcomp_nl "$(__git_heads)"
                else
-                       __gitcomp "$(__git_refs)"
+                       __gitcomp_nl "$(__git_refs)"
                fi
                ;;
        esac
@@ -1167,8 +1167,6 @@ _git_branch ()
 
 _git_bundle ()
 {
-       local words cword
-       _get_comp_words_by_ref -n =: words cword
        local cmd="${words[2]}"
        case "$cword" in
        2)
@@ -1191,8 +1189,6 @@ _git_checkout ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --conflict=*)
                __gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1210,7 +1206,7 @@ _git_checkout ()
                if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
                        track=''
                fi
-               __gitcomp "$(__git_refs '' $track)"
+               __gitcomp_nl "$(__git_refs '' $track)"
                ;;
        esac
 }
@@ -1222,14 +1218,12 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--edit --no-commit"
                ;;
        *)
-               __gitcomp "$(__git_refs)"
+               __gitcomp_nl "$(__git_refs)"
                ;;
        esac
 }
@@ -1238,8 +1232,6 @@ _git_clean ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--dry-run --quiet"
@@ -1251,8 +1243,6 @@ _git_clean ()
 
 _git_clone ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
@@ -1279,20 +1269,15 @@ _git_commit ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        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=}"
+       --reuse-message=*|--reedit-message=*|\
+       --fixup=*|--squash=*)
+               __gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
                return
                ;;
        --untracked-files=*)
@@ -1306,7 +1291,7 @@ _git_commit ()
                        --dry-run --reuse-message= --reedit-message=
                        --reset-author --file= --message= --template=
                        --cleanup= --untracked-files --untracked-files=
-                       --verbose --quiet
+                       --verbose --quiet --fixup= --squash=
                        "
                return
        esac
@@ -1315,8 +1300,6 @@ _git_commit ()
 
 _git_describe ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
@@ -1325,7 +1308,7 @@ _git_describe ()
                        "
                return
        esac
-       __gitcomp "$(__git_refs)"
+       __gitcomp_nl "$(__git_refs)"
 }
 
 __git_diff_common_options="--stat --numstat --shortstat --summary
@@ -1348,8 +1331,6 @@ _git_diff ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1370,8 +1351,6 @@ _git_difftool ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --tool=*)
                __gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1396,8 +1375,6 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "$__git_fetch_options"
@@ -1409,8 +1386,6 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --thread=*)
                __gitcomp "
@@ -1442,8 +1417,6 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
@@ -1458,8 +1431,6 @@ _git_fsck ()
 
 _git_gc ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--prune --aggressive"
@@ -1474,19 +1445,22 @@ _git_gitk ()
        _gitk
 }
 
+__git_match_ctag() {
+       awk "/^${1////\\/}/ { print \$1 }" "$2"
+}
+
 _git_grep ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
                        --cached
                        --text --ignore-case --word-regexp --invert-match
-                       --full-name
+                       --full-name --line-number
                        --extended-regexp --basic-regexp --fixed-strings
+                       --perl-regexp
                        --files-with-matches --name-only
                        --files-without-match
                        --max-depth
@@ -1497,13 +1471,20 @@ _git_grep ()
                ;;
        esac
 
-       __gitcomp "$(__git_refs)"
+       case "$cword,$prev" in
+       2,*|*,-*)
+               if test -r tags; then
+                       __gitcomp_nl "$(__git_match_ctag "$cur" tags)"
+                       return
+               fi
+               ;;
+       esac
+
+       __gitcomp_nl "$(__git_refs)"
 }
 
 _git_help ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--all --info --man --web"
@@ -1514,15 +1495,13 @@ _git_help ()
        __gitcomp "$__git_all_commands $(__git_aliases)
                attributes cli core-tutorial cvs-migration
                diffcore gitk glossary hooks ignore modules
-               repository-layout tutorial tutorial-2
+               namespaces repository-layout tutorial tutorial-2
                workflows
                "
 }
 
 _git_init ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --shared=*)
                __gitcomp "
@@ -1542,8 +1521,6 @@ _git_ls_files ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--cached --deleted --modified --others --ignored
@@ -1561,7 +1538,7 @@ _git_ls_files ()
 
 _git_ls_remote ()
 {
-       __gitcomp "$(__git_remotes)"
+       __gitcomp_nl "$(__git_remotes)"
 }
 
 _git_ls_tree ()
@@ -1584,7 +1561,7 @@ __git_log_common_options="
 __git_log_gitk_options="
        --dense --sparse --full-history
        --simplify-merges --simplify-by-decoration
-       --left-right
+       --left-right --notes --no-notes
 "
 # Options that go well for log and shortlog (not gitk)
 __git_log_shortlog_options="
@@ -1604,17 +1581,10 @@ _git_log ()
        if [ -f "$g/MERGE_HEAD" ]; then
                merge="--merge"
        fi
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
-       --pretty=*)
-               __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
-                       " "" "${cur##--pretty=}"
-               return
-               ;;
-       --format=*)
+       --pretty=*|--format=*)
                __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
-                       " "" "${cur##--format=}"
+                       " "" "${cur#*=}"
                return
                ;;
        --date=*)
@@ -1659,20 +1629,16 @@ _git_merge ()
 {
        __git_complete_strategy && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "$__git_merge_options"
                return
        esac
-       __gitcomp "$(__git_refs)"
+       __gitcomp_nl "$(__git_refs)"
 }
 
 _git_mergetool ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --tool=*)
                __gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1688,13 +1654,11 @@ _git_mergetool ()
 
 _git_merge_base ()
 {
-       __gitcomp "$(__git_refs)"
+       __gitcomp_nl "$(__git_refs)"
 }
 
 _git_mv ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--dry-run"
@@ -1713,8 +1677,6 @@ _git_notes ()
 {
        local subcommands='add append copy edit list prune remove show'
        local subcommand="$(__git_find_on_cmdline "$subcommands")"
-       local cur words cword
-       _get_comp_words_by_ref -n =: cur words cword
 
        case "$subcommand,$cur" in
        ,--*)
@@ -1723,18 +1685,16 @@ _git_notes ()
        ,*)
                case "${words[cword-1]}" in
                --ref)
-                       __gitcomp "$(__git_refs)"
+                       __gitcomp_nl "$(__git_refs)"
                        ;;
                *)
                        __gitcomp "$subcommands --ref"
                        ;;
                esac
                ;;
-       add,--reuse-message=*|append,--reuse-message=*)
-               __gitcomp "$(__git_refs)" "" "${cur##--reuse-message=}"
-               ;;
+       add,--reuse-message=*|append,--reuse-message=*|\
        add,--reedit-message=*|append,--reedit-message=*)
-               __gitcomp "$(__git_refs)" "" "${cur##--reedit-message=}"
+               __gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
                ;;
        add,--*|append,--*)
                __gitcomp '--file= --message= --reedit-message=
@@ -1753,7 +1713,7 @@ _git_notes ()
                -m|-F)
                        ;;
                *)
-                       __gitcomp "$(__git_refs)"
+                       __gitcomp_nl "$(__git_refs)"
                        ;;
                esac
                ;;
@@ -1764,8 +1724,6 @@ _git_pull ()
 {
        __git_complete_strategy && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
@@ -1781,22 +1739,20 @@ _git_pull ()
 
 _git_push ()
 {
-       local cur prev
-       _get_comp_words_by_ref -n =: cur prev
        case "$prev" in
        --repo)
-               __gitcomp "$(__git_remotes)"
+               __gitcomp_nl "$(__git_remotes)"
                return
        esac
        case "$cur" in
        --repo=*)
-               __gitcomp "$(__git_remotes)" "" "${cur##--repo=}"
+               __gitcomp_nl "$(__git_remotes)" "" "${cur##--repo=}"
                return
                ;;
        --*)
                __gitcomp "
                        --all --mirror --tags --dry-run --force --verbose
-                       --receive-pack= --repo=
+                       --receive-pack= --repo= --set-upstream
                "
                return
                ;;
@@ -1807,8 +1763,6 @@ _git_push ()
 _git_rebase ()
 {
        local dir="$(__gitdir)"
-       local cur
-       _get_comp_words_by_ref -n =: cur
        if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
                __gitcomp "--continue --skip --abort"
                return
@@ -1830,7 +1784,7 @@ _git_rebase ()
 
                return
        esac
-       __gitcomp "$(__git_refs)"
+       __gitcomp_nl "$(__git_refs)"
 }
 
 _git_reflog ()
@@ -1841,7 +1795,7 @@ _git_reflog ()
        if [ -z "$subcommand" ]; then
                __gitcomp "$subcommands"
        else
-               __gitcomp "$(__git_refs)"
+               __gitcomp_nl "$(__git_refs)"
        fi
 }
 
@@ -1850,8 +1804,6 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --confirm=*)
                __gitcomp "
@@ -1893,8 +1845,6 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-       local words cword
-       _get_comp_words_by_ref -n =: words cword
        local prevword word config_file= c=$cword
        while [ $c -gt 1 ]; do
                word="${words[c]}"
@@ -1925,27 +1875,29 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-       local cur prev
-       _get_comp_words_by_ref -n =: cur prev
        case "$prev" in
        branch.*.remote)
-               __gitcomp "$(__git_remotes)"
+               __gitcomp_nl "$(__git_remotes)"
                return
                ;;
        branch.*.merge)
-               __gitcomp "$(__git_refs)"
+               __gitcomp_nl "$(__git_refs)"
                return
                ;;
        remote.*.fetch)
                local remote="${prev#remote.}"
                remote="${remote%.fetch}"
-               __gitcomp "$(__git_refs_remotes "$remote")"
+               if [ -z "$cur" ]; then
+                       COMPREPLY=("refs/heads/")
+                       return
+               fi
+               __gitcomp_nl "$(__git_refs_remotes "$remote")"
                return
                ;;
        remote.*.push)
                local remote="${prev#remote.}"
                remote="${remote%.push}"
-               __gitcomp "$(git --git-dir="$(__gitdir)" \
+               __gitcomp_nl "$(git --git-dir="$(__gitdir)" \
                        for-each-ref --format='%(refname):%(refname)' \
                        refs/heads)"
                return
@@ -1992,7 +1944,7 @@ _git_config ()
                return
                ;;
        --get|--get-all|--unset|--unset-all)
-               __gitcomp "$(__git_config_get_set_variables)"
+               __gitcomp_nl "$(__git_config_get_set_variables)"
                return
                ;;
        *.*)
@@ -2012,70 +1964,60 @@ _git_config ()
                return
                ;;
        branch.*.*)
-               local pfx="${cur%.*}."
-               cur="${cur##*.}"
-               __gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur"
+               local pfx="${cur%.*}." cur_="${cur##*.}"
+               __gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur_"
                return
                ;;
        branch.*)
-               local pfx="${cur%.*}."
-               cur="${cur#*.}"
-               __gitcomp "$(__git_heads)" "$pfx" "$cur" "."
+               local pfx="${cur%.*}." cur_="${cur#*.}"
+               __gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "."
                return
                ;;
        guitool.*.*)
-               local pfx="${cur%.*}."
-               cur="${cur##*.}"
+               local pfx="${cur%.*}." cur_="${cur##*.}"
                __gitcomp "
                        argprompt cmd confirm needsfile noconsole norescan
                        prompt revprompt revunmerged title
-                       " "$pfx" "$cur"
+                       " "$pfx" "$cur_"
                return
                ;;
        difftool.*.*)
-               local pfx="${cur%.*}."
-               cur="${cur##*.}"
-               __gitcomp "cmd path" "$pfx" "$cur"
+               local pfx="${cur%.*}." cur_="${cur##*.}"
+               __gitcomp "cmd path" "$pfx" "$cur_"
                return
                ;;
        man.*.*)
-               local pfx="${cur%.*}."
-               cur="${cur##*.}"
-               __gitcomp "cmd path" "$pfx" "$cur"
+               local pfx="${cur%.*}." cur_="${cur##*.}"
+               __gitcomp "cmd path" "$pfx" "$cur_"
                return
                ;;
        mergetool.*.*)
-               local pfx="${cur%.*}."
-               cur="${cur##*.}"
-               __gitcomp "cmd path trustExitCode" "$pfx" "$cur"
+               local pfx="${cur%.*}." cur_="${cur##*.}"
+               __gitcomp "cmd path trustExitCode" "$pfx" "$cur_"
                return
                ;;
        pager.*)
-               local pfx="${cur%.*}."
-               cur="${cur#*.}"
+               local pfx="${cur%.*}." cur_="${cur#*.}"
                __git_compute_all_commands
-               __gitcomp "$__git_all_commands" "$pfx" "$cur"
+               __gitcomp_nl "$__git_all_commands" "$pfx" "$cur_"
                return
                ;;
        remote.*.*)
-               local pfx="${cur%.*}."
-               cur="${cur##*.}"
+               local pfx="${cur%.*}." cur_="${cur##*.}"
                __gitcomp "
                        url proxy fetch push mirror skipDefaultUpdate
                        receivepack uploadpack tagopt pushurl
-                       " "$pfx" "$cur"
+                       " "$pfx" "$cur_"
                return
                ;;
        remote.*)
-               local pfx="${cur%.*}."
-               cur="${cur#*.}"
-               __gitcomp "$(__git_remotes)" "$pfx" "$cur" "."
+               local pfx="${cur%.*}." cur_="${cur#*.}"
+               __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
                return
                ;;
        url.*.*)
-               local pfx="${cur%.*}."
-               cur="${cur##*.}"
-               __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur"
+               local pfx="${cur%.*}." cur_="${cur##*.}"
+               __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_"
                return
                ;;
        esac
@@ -2371,7 +2313,7 @@ _git_remote ()
 
        case "$subcommand" in
        rename|rm|show|prune)
-               __gitcomp "$(__git_remotes)"
+               __gitcomp_nl "$(__git_remotes)"
                ;;
        update)
                local i c='' IFS=$'\n'
@@ -2389,43 +2331,37 @@ _git_remote ()
 
 _git_replace ()
 {
-       __gitcomp "$(__git_refs)"
+       __gitcomp_nl "$(__git_refs)"
 }
 
 _git_reset ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--merge --mixed --hard --soft --patch"
                return
                ;;
        esac
-       __gitcomp "$(__git_refs)"
+       __gitcomp_nl "$(__git_refs)"
 }
 
 _git_revert ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--edit --mainline --no-edit --no-commit --signoff"
                return
                ;;
        esac
-       __gitcomp "$(__git_refs)"
+       __gitcomp_nl "$(__git_refs)"
 }
 
 _git_rm ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2439,8 +2375,6 @@ _git_shortlog ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
@@ -2458,17 +2392,10 @@ _git_show ()
 {
        __git_has_doubledash && return
 
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
-       --pretty=*)
-               __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
-                       " "" "${cur##--pretty=}"
-               return
-               ;;
-       --format=*)
+       --pretty=*|--format=*)
                __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
-                       " "" "${cur##--format=}"
+                       " "" "${cur#*=}"
                return
                ;;
        --*)
@@ -2483,8 +2410,6 @@ _git_show ()
 
 _git_show_branch ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
@@ -2501,8 +2426,6 @@ _git_show_branch ()
 
 _git_stash ()
 {
-       local cur
-       _get_comp_words_by_ref -n =: cur
        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")"
@@ -2531,7 +2454,7 @@ _git_stash ()
                        COMPREPLY=()
                        ;;
                show,*|apply,*|drop,*|pop,*|branch,*)
-                       __gitcomp "$(git --git-dir="$(__gitdir)" stash list \
+                       __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \
                                        | sed -n -e 's/:.*//p')"
                        ;;
                *)
@@ -2547,8 +2470,6 @@ _git_submodule ()
 
        local subcommands="add status init update summary foreach sync"
        if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-               local cur
-               _get_comp_words_by_ref -n =: cur
                case "$cur" in
                --*)
                        __gitcomp "--quiet --cached"
@@ -2592,8 +2513,6 @@ _git_svn ()
                        --edit --rmdir --find-copies-harder --copy-similarity=
                        "
 
-               local cur
-               _get_comp_words_by_ref -n =: cur
                case "$subcommand,$cur" in
                fetch,--*)
                        __gitcomp "--revision= --fetch-all $fc_opts"
@@ -2665,13 +2584,11 @@ _git_svn ()
 _git_tag ()
 {
        local i c=1 f=0
-       local words cword prev
-       _get_comp_words_by_ref -n =: words cword prev
        while [ $c -lt $cword ]; do
                i="${words[c]}"
                case "$i" in
                -d|-v)
-                       __gitcomp "$(__git_tags)"
+                       __gitcomp_nl "$(__git_tags)"
                        return
                        ;;
                -f)
@@ -2687,13 +2604,13 @@ _git_tag ()
                ;;
        -*|tag)
                if [ $f = 1 ]; then
-                       __gitcomp "$(__git_tags)"
+                       __gitcomp_nl "$(__git_tags)"
                else
                        COMPREPLY=()
                fi
                ;;
        *)
-               __gitcomp "$(__git_refs)"
+               __gitcomp_nl "$(__git_refs)"
                ;;
        esac
 }
@@ -2716,8 +2633,8 @@ _git ()
                typeset -h words
        fi
 
-       local cur words cword
-       _get_comp_words_by_ref -n =: cur words cword
+       local cur words cword prev
+       _get_comp_words_by_ref -n =: cur words cword prev
        while [ $c -lt $cword ]; do
                i="${words[c]}"
                case "$i" in
@@ -2741,6 +2658,7 @@ _git ()
                        --exec-path
                        --html-path
                        --work-tree=
+                       --namespace=
                        --help
                        "
                        ;;
@@ -2771,15 +2689,16 @@ _gitk ()
                typeset -h words
        fi
 
+       local cur words cword prev
+       _get_comp_words_by_ref -n =: cur words cword prev
+
        __git_has_doubledash && return
 
-       local cur
        local g="$(__gitdir)"
        local merge=""
        if [ -f "$g/MERGE_HEAD" ]; then
                merge="--merge"
        fi
-       _get_comp_words_by_ref -n =: cur
        case "$cur" in
        --*)
                __gitcomp "
@@ -2808,7 +2727,7 @@ complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
 fi
 
 if [[ -n ${ZSH_VERSION-} ]]; then
-       shopt () {
+       __git_shopt () {
                local option
                if [ $# -ne 2 ]; then
                        echo "USAGE: $0 (-q|-s|-u) <option>" >&2
@@ -2831,4 +2750,8 @@ if [[ -n ${ZSH_VERSION-} ]]; then
                        return 1
                esac
        }
+else
+       __git_shopt () {
+               shopt "$@"
+       }
 fi