blame: handle --first-parent
[gitweb.git] / contrib / completion / git-completion.bash
index 67736c2a9c9aba150ca1ec8e2f14e803e84a125d..c97c648d7e07fe9eeea1b1afff1ce55ac730cf4f 100644 (file)
@@ -1,5 +1,3 @@
-#!bash
-#
 # bash/zsh completion support for core Git.
 #
 # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
 #
 # To use these routines:
 #
-#    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
+#    1) Copy this file to somewhere (e.g. ~/.git-completion.bash).
 #    2) Add the following line to your .bashrc/.zshrc:
-#        source ~/.git-completion.sh
+#        source ~/.git-completion.bash
 #    3) Consider changing your PS1 to also show the current branch,
 #       see git-prompt.sh for details.
+#
+# If you use complex aliases of form '!f() { ... }; f', you can use the null
+# command ':' as the first command in the function body to declare the desired
+# completion style.  For example '!f() { : git commit ; ... }; f' will
+# tell the completion to use commit completion.  This also works with aliases
+# of form "!sh -c '...'".  For example, "!sh -c ': git commit ; ... '".
 
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
@@ -33,8 +37,6 @@ esac
 # returns location of .git repo
 __gitdir ()
 {
-       # Note: this function is duplicated in git-prompt.sh
-       # When updating it, make sure you update the other one to match.
        if [ -z "${1-}" ]; then
                if [ -n "${__git_dir-}" ]; then
                        echo "$__git_dir"
@@ -182,9 +184,9 @@ _get_comp_words_by_ref ()
 }
 fi
 
-__gitcompadd ()
+__gitcompappend ()
 {
-       local i=0
+       local x i=${#COMPREPLY[@]}
        for x in $1; do
                if [[ "$x" == "$3"* ]]; then
                        COMPREPLY[i++]="$2$x$4"
@@ -192,6 +194,12 @@ __gitcompadd ()
        done
 }
 
+__gitcompadd ()
+{
+       COMPREPLY=()
+       __gitcompappend "$@"
+}
+
 # Generates completion reply, appending a space to possible completion words,
 # if necessary.
 # It accepts 1 to 4 arguments:
@@ -222,6 +230,14 @@ __gitcomp ()
        esac
 }
 
+# Variation of __gitcomp_nl () that appends to the existing list of
+# completion candidates, COMPREPLY.
+__gitcomp_nl_append ()
+{
+       local IFS=$'\n'
+       __gitcompappend "$1" "${2-}" "${3-$cur}" "${4- }"
+}
+
 # Generates completion reply from newline-separated possible completion words
 # by appending a space to all of them.
 # It accepts 1 to 4 arguments:
@@ -233,8 +249,8 @@ __gitcomp ()
 #    appended.
 __gitcomp_nl ()
 {
-       local IFS=$'\n'
-       __gitcompadd "$1" "${2-}" "${3-$cur}" "${4- }"
+       COMPREPLY=()
+       __gitcomp_nl_append "$@"
 }
 
 # Generates completion reply with compgen from newline-separated possible
@@ -252,106 +268,46 @@ __gitcomp_file ()
        # since tilde expansion is not applied.
        # This means that COMPREPLY will be empty and Bash default
        # completion will be used.
-       COMPREPLY=($(compgen -P "${2-}" -W "$1" -- "${3-$cur}"))
+       __gitcompadd "$1" "${2-}" "${3-$cur}" ""
 
-       # Tell Bash that compspec generates filenames.
-       compopt -o filenames 2>/dev/null
+       # use a hack to enable file mode in bash < 4
+       compopt -o filenames +o nospace 2>/dev/null ||
+       compgen -f /non-existing-dir/ > /dev/null
 }
 
-__git_index_file_list_filter_compat ()
-{
-       local path
-
-       while read -r path; do
-               case "$path" in
-               ?*/*) echo "${path%%/*}/" ;;
-               *) echo "$path" ;;
-               esac
-       done
-}
-
-__git_index_file_list_filter_bash ()
-{
-       local path
-
-       while read -r path; do
-               case "$path" in
-               ?*/*)
-                       # XXX if we append a slash to directory names when using
-                       # `compopt -o filenames`, Bash will append another slash.
-                       # This is pretty stupid, and this the reason why we have to
-                       # define a compatible version for this function.
-                       echo "${path%%/*}" ;;
-               *)
-                       echo "$path" ;;
-               esac
-       done
-}
-
-# Process path list returned by "ls-files" and "diff-index --name-only"
-# commands, in order to list only file names relative to a specified
-# directory, and append a slash to directory names.
-__git_index_file_list_filter ()
-{
-       # Default to Bash >= 4.x
-       __git_index_file_list_filter_bash
-}
-
-# Execute git ls-files, returning paths relative to the directory
-# specified in the first argument, and using the options specified in
-# the second argument.
+# Execute 'git ls-files', unless the --committable option is specified, in
+# which case it runs 'git diff-index' to find out the files that can be
+# committed.  It return paths relative to the directory specified in the first
+# argument, and using the options specified in the second argument.
 __git_ls_files_helper ()
 {
-       (
-               test -n "${CDPATH+set}" && unset CDPATH
+       if [ "$2" == "--committable" ]; then
+               git -C "$1" diff-index --name-only --relative HEAD
+       else
                # NOTE: $2 is not quoted in order to support multiple options
-               cd "$1" && git ls-files --exclude-standard $2
-       ) 2>/dev/null
+               git -C "$1" ls-files --exclude-standard $2
+       fi 2>/dev/null
 }
 
 
-# Execute git diff-index, returning paths relative to the directory
-# specified in the first argument, and using the tree object id
-# specified in the second argument.
-__git_diff_index_helper ()
-{
-       (
-               test -n "${CDPATH+set}" && unset CDPATH
-               cd "$1" && git diff-index --name-only --relative "$2"
-       ) 2>/dev/null
-}
-
 # __git_index_files accepts 1 or 2 arguments:
 # 1: Options to pass to ls-files (required).
-#    Supported options are --cached, --modified, --deleted, --others,
-#    and --directory.
 # 2: A directory path (optional).
 #    If provided, only files within the specified directory are listed.
 #    Sub directories are never recursed.  Path must have a trailing
 #    slash.
 __git_index_files ()
 {
-       local dir="$(__gitdir)" root="${2-.}"
+       local dir="$(__gitdir)" root="${2-.}" file
 
        if [ -d "$dir" ]; then
-               __git_ls_files_helper "$root" "$1" | __git_index_file_list_filter |
-                       sort | uniq
-       fi
-}
-
-# __git_diff_index_files accepts 1 or 2 arguments:
-# 1) The id of a tree object.
-# 2) A directory path (optional).
-#    If provided, only files within the specified directory are listed.
-#    Sub directories are never recursed.  Path must have a trailing
-#    slash.
-__git_diff_index_files ()
-{
-       local dir="$(__gitdir)" root="${2-.}"
-
-       if [ -d "$dir" ]; then
-               __git_diff_index_helper "$root" "$1" | __git_index_file_list_filter |
-                       sort | uniq
+               __git_ls_files_helper "$root" "$1" |
+               while read -r file; do
+                       case "$file" in
+                       ?*/*) echo "${file%%/*}" ;;
+                       *) echo "$file" ;;
+                       esac
+               done | sort | uniq
        fi
 }
 
@@ -427,14 +383,9 @@ __git_refs ()
                done
                ;;
        *)
-               git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \
-               while read -r hash i; do
-                       case "$i" in
-                       *^{}) ;;
-                       refs/*) echo "${i#refs/*/}" ;;
-                       *) echo "$i" ;;
-                       esac
-               done
+               echo "HEAD"
+               git for-each-ref --format="%(refname:short)" -- \
+                       "refs/remotes/$dir/" 2>/dev/null | sed -e "s#^$dir/##"
                ;;
        esac
 }
@@ -460,12 +411,9 @@ __git_refs_remotes ()
 
 __git_remotes ()
 {
-       local i IFS=$'\n' d="$(__gitdir)"
+       local d="$(__gitdir)"
        test -d "$d/remotes" && ls -1 "$d/remotes"
-       for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do
-               i="${i#remote.}"
-               echo "${i/.url*/}"
-       done
+       git --git-dir="$d" remote
 }
 
 __git_list_merge_strategies ()
@@ -552,44 +500,23 @@ __git_complete_revlist_file ()
 }
 
 
-# __git_complete_index_file requires 1 argument: the options to pass to
-# ls-file
+# __git_complete_index_file requires 1 argument:
+# 1: the options to pass to ls-file
+#
+# The exception is --committable, which finds the files appropriate commit.
 __git_complete_index_file ()
 {
-       local pfx cur_="$cur"
+       local pfx="" cur_="$cur"
 
        case "$cur_" in
        ?*/*)
                pfx="${cur_%/*}"
                cur_="${cur_##*/}"
                pfx="${pfx}/"
-
-               __gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_"
-               ;;
-       *)
-               __gitcomp_file "$(__git_index_files "$1")" "" "$cur_"
                ;;
        esac
-}
-
-# __git_complete_diff_index_file requires 1 argument: the id of a tree
-# object
-__git_complete_diff_index_file ()
-{
-       local pfx cur_="$cur"
 
-       case "$cur_" in
-       ?*/*)
-               pfx="${cur_%/*}"
-               cur_="${cur_##*/}"
-               pfx="${pfx}/"
-
-               __gitcomp_file "$(__git_diff_index_files "$1" "$pfx")" "$pfx" "$cur_"
-               ;;
-       *)
-               __gitcomp_file "$(__git_diff_index_files "$1")" "" "$cur_"
-               ;;
-       esac
+       __gitcomp_file "$(__git_index_files "$1" ${pfx:+"$pfx"})" "$pfx" "$cur_"
 }
 
 __git_complete_file ()
@@ -733,12 +660,13 @@ __git_list_porcelain_commands ()
                cat-file)         : plumbing;;
                check-attr)       : plumbing;;
                check-ignore)     : plumbing;;
+               check-mailmap)    : plumbing;;
                check-ref-format) : plumbing;;
                checkout-index)   : plumbing;;
                commit-tree)      : plumbing;;
                count-objects)    : infrequent;;
-               credential-cache) : credentials helper;;
-               credential-store) : credentials helper;;
+               credential)       : credentials;;
+               credential-*)     : credentials helper;;
                cvsexportcommit)  : export;;
                cvsimport)        : import;;
                cvsserver)        : daemon;;
@@ -757,7 +685,6 @@ __git_list_porcelain_commands ()
                index-pack)       : plumbing;;
                init-db)          : deprecated;;
                local-fetch)      : plumbing;;
-               lost-found)       : infrequent;;
                ls-files)         : plumbing;;
                ls-remote)        : plumbing;;
                ls-tree)          : plumbing;;
@@ -771,14 +698,12 @@ __git_list_porcelain_commands ()
                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;;
                remote-*)         : transport;;
-               repo-config)      : deprecated;;
                rerere)           : plumbing;;
                rev-list)         : plumbing;;
                rev-parse)        : plumbing;;
@@ -791,7 +716,6 @@ __git_list_porcelain_commands ()
                ssh-*)            : transport;;
                stripspace)       : plumbing;;
                symbolic-ref)     : plumbing;;
-               tar-tree)         : deprecated;;
                unpack-file)      : plumbing;;
                unpack-objects)   : plumbing;;
                update-index)     : plumbing;;
@@ -811,35 +735,29 @@ __git_list_porcelain_commands ()
 __git_porcelain_commands=
 __git_compute_porcelain_commands ()
 {
-       __git_compute_all_commands
        test -n "$__git_porcelain_commands" ||
        __git_porcelain_commands=$(__git_list_porcelain_commands)
 }
 
-__git_pretty_aliases ()
+# Lists all set config variables starting with the given section prefix,
+# with the prefix removed.
+__git_get_config_variables ()
 {
-       local i IFS=$'\n'
-       for i in $(git --git-dir="$(__gitdir)" config --get-regexp "pretty\..*" 2>/dev/null); do
-               case "$i" in
-               pretty.*)
-                       i="${i#pretty.}"
-                       echo "${i/ */}"
-                       ;;
-               esac
+       local section="$1" i IFS=$'\n'
+       for i in $(git --git-dir="$(__gitdir)" config --get-regexp "^$section\..*" 2>/dev/null); do
+               i="${i#$section.}"
+               echo "${i/ */}"
        done
 }
 
+__git_pretty_aliases ()
+{
+       __git_get_config_variables "pretty"
+}
+
 __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_get_config_variables "alias"
 }
 
 # __git_aliased_command requires 1 argument
@@ -857,6 +775,10 @@ __git_aliased_command ()
                -*)     : option ;;
                *=*)    : setting env ;;
                git)    : git itself ;;
+               \(\))   : skip parens of shell function definition ;;
+               {)      : skip start of shell helper function ;;
+               :)      : skip null command ;;
+               \'*)    : skip opening quote after sh -c ;;
                *)
                        echo "$word"
                        return
@@ -985,7 +907,7 @@ _git_add ()
        esac
 
        # XXX should we check for --update and --all options ?
-       __git_complete_index_file "--others --modified"
+       __git_complete_index_file "--others --modified --directory --no-empty-directory"
 }
 
 _git_archive ()
@@ -1049,7 +971,7 @@ _git_branch ()
 
        case "$cur" in
        --set-upstream-to=*)
-               __gitcomp "$(__git_refs)" "" "${cur##--set-upstream-to=}"
+               __gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}"
                ;;
        --*)
                __gitcomp "
@@ -1117,7 +1039,7 @@ _git_checkout ()
 
 _git_cherry ()
 {
-       __gitcomp "$(__git_refs)"
+       __gitcomp_nl "$(__git_refs)"
 }
 
 _git_cherry_pick ()
@@ -1147,7 +1069,7 @@ _git_clean ()
        esac
 
        # XXX should we check for -x option ?
-       __git_complete_index_file "--others"
+       __git_complete_index_file "--others --directory"
 }
 
 _git_clone ()
@@ -1186,7 +1108,7 @@ _git_commit ()
 
        case "$cur" in
        --cleanup=*)
-               __gitcomp "default strip verbatim whitespace
+               __gitcomp "default scissors strip verbatim whitespace
                        " "" "${cur##--cleanup=}"
                return
                ;;
@@ -1213,7 +1135,7 @@ _git_commit ()
        esac
 
        if git rev-parse --verify --quiet HEAD >/dev/null; then
-               __git_complete_diff_index_file "HEAD"
+               __git_complete_index_file "--committable"
        else
                # This is the first commit
                __git_complete_index_file "--cached"
@@ -1241,12 +1163,12 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
                        --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
+                       --ignore-all-space --ignore-blank-lines --exit-code
+                       --quiet --ext-diff --no-ext-diff
                        --no-prefix --src-prefix= --dst-prefix=
                        --inter-hunk-context=
                        --patience --histogram --minimal
-                       --raw
+                       --raw --word-diff
                        --dirstat --dirstat= --dirstat-by-file
                        --dirstat-by-file= --cumulative
                        --diff-algorithm=
@@ -1272,8 +1194,8 @@ _git_diff ()
        __git_complete_revlist_file
 }
 
-__git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
-                       tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc3 codecompare
+__git_mergetools_common="diffuse diffmerge ecmerge emerge kdiff3 meld opendiff
+                       tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc codecompare
 "
 
 _git_difftool ()
@@ -1294,17 +1216,23 @@ _git_difftool ()
                return
                ;;
        esac
-       __git_complete_file
+       __git_complete_revlist_file
 }
 
+__git_fetch_recurse_submodules="yes on-demand no"
+
 __git_fetch_options="
        --quiet --verbose --append --upload-pack --force --keep --depth=
-       --tags --no-tags --all --prune --dry-run
+       --tags --no-tags --all --prune --dry-run --recurse-submodules=
 "
 
 _git_fetch ()
 {
        case "$cur" in
+       --recurse-submodules=*)
+               __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}"
+               return
+               ;;
        --*)
                __gitcomp "$__git_fetch_options"
                return
@@ -1368,7 +1296,7 @@ _git_gitk ()
 }
 
 __git_match_ctag() {
-       awk "/^${1////\\/}/ { print \$1 }" "$2"
+       awk "/^${1//\//\\/}/ { print \$1 }" "$2"
 }
 
 _git_grep ()
@@ -1488,7 +1416,7 @@ __git_log_gitk_options="
 # Options that go well for log and shortlog (not gitk)
 __git_log_shortlog_options="
        --author= --committer= --grep=
-       --all-match
+       --all-match --invert-grep
 "
 
 __git_log_pretty_formats="oneline short medium full fuller email raw format:"
@@ -1514,7 +1442,7 @@ _git_log ()
                return
                ;;
        --decorate=*)
-               __gitcomp "long short" "" "${cur##--decorate=}"
+               __gitcomp "full short no" "" "${cur##--decorate=}"
                return
                ;;
        --*)
@@ -1527,6 +1455,7 @@ _git_log ()
                        --abbrev-commit --abbrev=
                        --relative-date --date=
                        --pretty= --format= --oneline
+                       --show-signature
                        --cherry-pick
                        --graph
                        --decorate --decorate=
@@ -1542,9 +1471,12 @@ _git_log ()
        __git_complete_revlist
 }
 
+# Common merge options shared by git-merge(1) and git-pull(1).
 __git_merge_options="
        --no-commit --no-stat --log --no-log --squash --strategy
        --commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit
+       --verify-signatures --no-verify-signatures --gpg-sign
+       --quiet --verbose --progress --no-progress
 "
 
 _git_merge ()
@@ -1553,7 +1485,8 @@ _git_merge ()
 
        case "$cur" in
        --*)
-               __gitcomp "$__git_merge_options"
+               __gitcomp "$__git_merge_options
+                       --rerere-autoupdate --no-rerere-autoupdate --abort"
                return
        esac
        __gitcomp_nl "$(__git_refs)"
@@ -1575,6 +1508,12 @@ _git_mergetool ()
 
 _git_merge_base ()
 {
+       case "$cur" in
+       --*)
+               __gitcomp "--octopus --independent --is-ancestor --fork-point"
+               return
+               ;;
+       esac
        __gitcomp_nl "$(__git_refs)"
 }
 
@@ -1653,6 +1592,10 @@ _git_pull ()
        __git_complete_strategy && return
 
        case "$cur" in
+       --recurse-submodules=*)
+               __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}"
+               return
+               ;;
        --*)
                __gitcomp "
                        --rebase --no-rebase
@@ -1665,22 +1608,55 @@ _git_pull ()
        __git_complete_remote_or_refspec
 }
 
+__git_push_recurse_submodules="check on-demand"
+
+__git_complete_force_with_lease ()
+{
+       local cur_=$1
+
+       case "$cur_" in
+       --*=)
+               ;;
+       *:*)
+               __gitcomp_nl "$(__git_refs)" "" "${cur_#*:}"
+               ;;
+       *)
+               __gitcomp_nl "$(__git_refs)" "" "$cur_"
+               ;;
+       esac
+}
+
 _git_push ()
 {
        case "$prev" in
        --repo)
                __gitcomp_nl "$(__git_remotes)"
                return
+               ;;
+       --recurse-submodules)
+               __gitcomp "$__git_push_recurse_submodules"
+               return
+               ;;
        esac
        case "$cur" in
        --repo=*)
                __gitcomp_nl "$(__git_remotes)" "" "${cur##--repo=}"
                return
                ;;
+       --recurse-submodules=*)
+               __gitcomp "$__git_push_recurse_submodules" "" "${cur##--recurse-submodules=}"
+               return
+               ;;
+       --force-with-lease=*)
+               __git_complete_force_with_lease "${cur##--force-with-lease=}"
+               return
+               ;;
        --*)
                __gitcomp "
                        --all --mirror --tags --dry-run --force --verbose
+                       --quiet --prune --delete --follow-tags
                        --receive-pack= --repo= --set-upstream
+                       --force-with-lease --force-with-lease= --recurse-submodules=
                "
                return
                ;;
@@ -1707,7 +1683,8 @@ _git_rebase ()
                        --preserve-merges --stat --no-stat
                        --committer-date-is-author-date --ignore-date
                        --ignore-whitespace --whitespace=
-                       --autosquash
+                       --autosquash --fork-point --no-fork-point
+                       --autostash
                        "
 
                return
@@ -1890,6 +1867,10 @@ _git_config ()
                __gitcomp "$__git_send_email_suppresscc_options"
                return
                ;;
+       sendemail.transferencoding)
+               __gitcomp "7bit 8bit quoted-printable base64"
+               return
+               ;;
        --get|--get-all|--unset|--unset-all)
                __gitcomp_nl "$(__git_config_get_set_variables)"
                return
@@ -1917,6 +1898,7 @@ _git_config ()
        branch.*)
                local pfx="${cur%.*}." cur_="${cur#*.}"
                __gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "."
+               __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_"
                return
                ;;
        guitool.*.*)
@@ -1959,6 +1941,7 @@ _git_config ()
        remote.*)
                local pfx="${cur%.*}." cur_="${cur#*.}"
                __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
+               __gitcomp_nl_append "pushdefault" "$pfx" "$cur_"
                return
                ;;
        url.*.*)
@@ -2022,6 +2005,7 @@ _git_config ()
                color.status.changed
                color.status.header
                color.status.nobranch
+               color.status.unmerged
                color.status.untracked
                color.status.updated
                color.ui
@@ -2042,7 +2026,6 @@ _git_config ()
                core.fileMode
                core.fsyncobjectfiles
                core.gitProxy
-               core.ignoreCygwinFSTricks
                core.ignoreStat
                core.ignorecase
                core.logAllRefUpdates
@@ -2082,6 +2065,7 @@ _git_config ()
                fetch.unpackLimit
                format.attach
                format.cc
+               format.coverLetter
                format.headers
                format.numbered
                format.pretty
@@ -2133,6 +2117,7 @@ _git_config ()
                http.noEPSV
                http.postBuffer
                http.proxy
+               http.sslCipherList
                http.sslCAInfo
                http.sslCAPath
                http.sslCert
@@ -2196,6 +2181,7 @@ _git_config ()
                pull.octopus
                pull.twohead
                push.default
+               push.followTags
                rebase.autosquash
                rebase.stat
                receive.autogc
@@ -2269,12 +2255,7 @@ _git_remote ()
                __git_complete_remote_or_refspec
                ;;
        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"
+               __gitcomp "$(__git_get_config_variables "remotes")"
                ;;
        *)
                ;;
@@ -2301,6 +2282,11 @@ _git_reset ()
 
 _git_revert ()
 {
+       local dir="$(__gitdir)"
+       if [ -f "$dir"/REVERT_HEAD ]; then
+               __gitcomp "--continue --quit --abort"
+               return
+       fi
        case "$cur" in
        --*)
                __gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2355,12 +2341,13 @@ _git_show ()
                ;;
        --*)
                __gitcomp "--pretty= --format= --abbrev-commit --oneline
+                       --show-signature
                        $__git_diff_common_options
                        "
                return
                ;;
        esac
-       __git_complete_file
+       __git_complete_revlist_file
 }
 
 _git_show_branch ()
@@ -2560,6 +2547,16 @@ _git_tag ()
                __gitcomp_nl "$(__git_refs)"
                ;;
        esac
+
+       case "$cur" in
+       --*)
+               __gitcomp "
+                       --list --delete --verify --annotate --message --file
+                       --sign --cleanup --local-user --force --column --sort
+                       --contains --points-at
+                       "
+               ;;
+       esac
 }
 
 _git_whatchanged ()
@@ -2575,9 +2572,10 @@ __git_main ()
                i="${words[c]}"
                case "$i" in
                --git-dir=*) __git_dir="${i#--git-dir=}" ;;
+               --git-dir)   ((c++)) ; __git_dir="${words[c]}" ;;
                --bare)      __git_dir="." ;;
                --help) command="help"; break ;;
-               -c) c=$((++c)) ;;
+               -c|--work-tree|--namespace) ((c++)) ;;
                -*) ;;
                *) command="$i"; break ;;
                esac
@@ -2595,6 +2593,7 @@ __git_main ()
                        --exec-path
                        --exec-path=
                        --html-path
+                       --man-path
                        --info-path
                        --work-tree=
                        --namespace=
@@ -2613,6 +2612,7 @@ __git_main ()
 
        local expansion=$(__git_aliased_command "$command")
        if [ -n "$expansion" ]; then
+               words[1]=$expansion
                completion_func="_git_${expansion//-/_}"
                declare -f $completion_func >/dev/null && $completion_func
        fi
@@ -2663,7 +2663,7 @@ if [[ -n ${ZSH_VERSION-} ]]; then
                                --*=*|*.) ;;
                                *) c="$c " ;;
                                esac
-                               array[$#array+1]="$c"
+                               array[${#array[@]}+1]="$c"
                        done
                        compset -P '*[=:]'
                        compadd -Q -S '' -p "${2-}" -a -- array && _ret=0
@@ -2702,14 +2702,6 @@ if [[ -n ${ZSH_VERSION-} ]]; then
 
        compdef _git git gitk
        return
-elif [[ -n ${BASH_VERSION-} ]]; then
-       if ((${BASH_VERSINFO[0]} < 4)); then
-               # compopt is not supported
-               __git_index_file_list_filter ()
-               {
-                       __git_index_file_list_filter_compat
-               }
-       fi
 fi
 
 __git_func_wrap ()