Ответ 1

zstyle :completion::complete:git-checkout:argument-rest:headrefs command "git for-each-ref --format='%(refname)' refs/heads 2>/dev/null"

Пояснение:

Ввод git checkout <Control-x><h> вызывает _complete_help, который предоставляет внутренности того, как система завершения zsh будет действовать, если вы нажали TAB в текущем контексте (вместо нажатия <Control-x><h>). Из этого можно видеть, что zsh будет вызывать функцию __git_heads для завершения имен заголовков ветвей git. Если вы затем наберете which __git_heads, вы увидите, что имена этих ветвей заголовка получаются с помощью:

_call_program headrefs git for-each-ref --format='"%(refname)"' refs/heads refs/remotes 2>/dev/null

К счастью для нас _call_program разработан специально, чтобы позволить пользователю изменять поведение по умолчанию. Поэтому приведенная выше команда zstyle указывает zsh использовать альтернативный вызов git for-each-ref ... вместо встроенного, и вы можете видеть, что в приведенном выше вызове я удалил параметр refs/remotes. Первый параметр zstyle - это контекст завершения, и здесь он означает "всякий раз, когда система завершения запрашивает завершение тега headrefs, когда пользователь завершает аргумент для git checkout. Таким образом, этот zstyle будет влиять только git checkout, а не любые другие подкоманды git.

Ответ 2

Похоже, что __git_heads теперь проверяет только локальные ветки, но файлы завершения вызывают __git_refs.

Я взломал это, применив этот патч к git-completion.bash, к которому проксируется команда zsh _git:

--- git-completion.bash.old 2015-04-02 16:09:38.000000000 -0700
+++ git-completion.bash     2015-04-02 16:10:24.000000000 -0700
@@ -1032,13 +1032,7 @@
                    "
            ;;
    *)
-           # check if --track, --no-track, or --no-guess was specified
-           # if so, disable DWIM mode
-           local flags="--track --no-track --no-guess" track=1
-           if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
-                   track=''
-           fi
-           __gitcomp_nl "$(__git_refs '' $track)"
+           __gitcomp_nl "$(__git_heads)"
            ;;
    esac
 }

Это не идеальное решение, но оно работает для моих случаев использования и делает завершение мгновенным, а не 10 секунд.

Ответ 3

Набрав git checkout <Ctrl-X><H>, вы увидите кучу тегов, некоторые из которых кажутся релевантными:

$ git checkout
tags in context :completion::complete:git-checkout:argument-rest:
    remote-branch-names-noprefix              (__git_describe_branch __git_describe_commit __git_remote_branch_names_noprefix _git-checkout _git) 
    heads-remote                              (__git_describe_branch __git_describe_commit __git_heads_remote __git_heads __git_commits __git_tree_ishs _git-checkout _git) 
    [...]

На первый взгляд нам нужно изменить поведение remote-branch-names-noprefix, чтобы прекратить предоставление удаленных имен ветвей без префикса.

Чтобы дважды проверить, посмотрим, с какими элементами связаны эти теги, используйте:

$ zstyle ':completion:*' group-name ''
$ zstyle ':completion:*' format 'Completing "%d":'
$ git checkout T<Tab>
Completing "remote branch name":
T3522-plugins_and_stuff  T7482
Completing "local head":
T7626-async

В скобках, следующих за именами тегов выше, существует цепочка команд, которая привела к созданию записи автозаполнения для этого тега. В цепочке remote-branch-names-noprefix вы можете увидеть __git_remote_branch_names_noprefix, которая кажется актуальной. Посмотрите /usr/share/zsh/functions/Completion/Unix/_git:

(( $+functions[__git_remote_branch_names_noprefix] )) ||
__git_remote_branch_names_noprefix () {
  declare -a heads

  branch_names=(${${${${(f)"$(_call_program remote-branch-refs-noprefix git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}#refs/remotes/}#*/}:#HEAD})
  __git_command_successful $pipestatus || return 1

  __git_describe_commit branch_names remote-branch-names-noprefix 'remote branch name' "[email protected]"
}

Вы можете увидеть, как _call_program используется для определения remote-branch-refs-noprefix. Мы хотим изменить это определение в случае git-checkout. Заменив его "эхо", он прекратит предоставление записей автозаполнения:

zstyle ':completion::complete:git-checkout:argument-rest:remote-branch-refs-noprefix' command "echo"

Ответ 4

Вы можете отключить автозаполнение на git checkout, добавив эту строку в ваш файл .zshrc:

compdef -d git checkout