![Zsh git 文件名补全“--git-dir=... --work-tree=...”:不是 git 存储库](https://linux22.com/image/107375/Zsh%20git%20%E6%96%87%E4%BB%B6%E5%90%8D%E8%A1%A5%E5%85%A8%E2%80%9C--git-dir%3D...%20--work-tree%3D...%E2%80%9D%EF%BC%9A%E4%B8%8D%E6%98%AF%20git%20%E5%AD%98%E5%82%A8%E5%BA%93.png)
我使用以下方法跟踪我的点文件:
- 裸存储库驻留在
$HOME/repos/dotfiles
. - 我的所有点文件都位于其正常位置,例如
$HOME/.vim/vimrc
,而不是$HOME/repos/dotfiles/vimrc
。 - 我跑步是
git --git-dir=$HOME/repos/dotfiles --work-tree=$HOME ...
为了管理事情。
(实际上,g()
当我处于 时,我有一个函数可以扩展到上面的命令$HOME
,否则就扩展到git
。)
一切都很好,除了......
问题:Zsh git 文件名补全不起作用。
例子:
% pwd
/home/brian
% g status ~
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: .vim/vimrc
modified: .xmonad/xmonad.hs
no changes added to commit (use "git add" and/or "git commit -a")
% g add <Tab>
Completing not a git repository
(“正在完成...”的内容是由于zstyle ':completion:*' format $'%{\e[0;31m%}Completing %B%d%b%{\e[0m%}'
。)
值得注意的是,以某种方式告诉 zsh 的 git 补全“移动到/跟随” 的给定值是不够的--work-tree
,就好像git
从该目录调用一样,因为明确地这样做也不起作用:
% cd repos/dotfiles
% g status
fatal: This operation must be run in a work tree
% g add <Tab>
Completing not a git repository
问题:有没有一种简单的方法可以将 zsh 的 git 补全扩展到这种情况?
答案1
zsh
遗憾的是,它是git 完成过程中的一个错误。您可以在“zsh”邮件列表上找到讨论这里。
Daniel Shahaf 确实提供了“_git”的补丁:
diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git
index 518e6d198..45a0fa622 100644
--- a/Completion/Unix/Command/_git
+++ b/Completion/Unix/Command/_git
@@ -6609,20 +6609,33 @@ __git_files_relative () {
(( $+functions[__git_files] )) ||
__git_files () {
local compadd_opts opts tag description gitcdup gitprefix files expl
+ local pref
zparseopts -D -E -a compadd_opts V: J: 1 2 n f X: M: P: S: r: R: q F:
zparseopts -D -E -a opts -- -cached -deleted -modified -others -ignored -unmerged -killed x+: --exclude+:
tag=$1 description=$2; shift 2
- gitcdup=$(_call_program gitcdup git rev-parse --show-cdup 2>/dev/null)
- __git_command_successful $pipestatus || return 1
+ case $(_call_program gitinworktree git rev-parse --is-inside-work-tree 2>/dev/null) in
+ (true)
+ gitcdup=$(_call_program gitcdup git rev-parse --show-cdup 2>/dev/null)
+ __git_command_successful $pipestatus || return 1
- gitprefix=$(_call_program gitprefix git rev-parse --show-prefix 2>/dev/null)
- __git_command_successful $pipestatus || return 1
+ gitprefix=$(_call_program gitprefix git rev-parse --show-prefix 2>/dev/null)
+ __git_command_successful $pipestatus || return 1
+
+ local pref=$gitcdup$gitprefix$PREFIX
+ ;;
+ (false)
+ local pref=
+ ;;
+ (*)
+ # XXX what to do?
+ return 1
+ ;;
+ esac
# TODO: --directory should probably be added to $opts when --others is given.
- local pref=$gitcdup$gitprefix$PREFIX
# First allow ls-files to pattern-match in case of remote repository
files=(${(0)"$(_call_program files git ls-files -z --exclude-standard ${(q)opts} -- ${(q)${pref:+$pref\\\*}} 2>/dev/null)"})
@@ -7585,7 +7598,8 @@ _git() {
;;
(option-or-argument)
curcontext=${curcontext%:*:*}:git-$words[1]:
- (( $+opt_args[--git-dir] )) && local -x GIT_DIR=$opt_args[--git-dir]
+ (( $+opt_args[--git-dir] )) && local -x GIT_DIR=${(e)opt_args[--git-dir]}
+ (( $+opt_args[--work-tree] )) && local -x GIT_WORK_TREE=${(e)opt_args[--work-tree]}
if ! _call_function ret _git-$words[1]; then
if zstyle -T :completion:$curcontext: use-fallback; then
_default && ret=0
它显然适用于zsh 5.4.1
但对我来说不起作用,YMMV。
当问题正在解决时,我会更新这个答案。
编辑:
使用上面的补丁它确实可以工作,但是你放置的位置add
很重要 - 它必须在最后:
git --git-dir=$HOME/.dotfiles --work-tree=$HOME/ add
还有一件事值得注意 - 它有点慢。
答案2
最新(2018-04-20)官方git补全效果很好。
https://github.com/git/git/tree/master/contrib/completion
安装,
mkdir -p ~/.zsh && cd $_
wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash
wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.zsh
wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh
# The default behavior for 'git <TAB><TAB>' is to show a 10+ lines 'common commands' list.
# I prefer a full list.
# Better way to modify?
sed -i.bak '/^__git_zsh_cmd_common/,/{/ s/{/{\n\treturn/' _git
# add zshrc settings
vi ~/.zshrc
fpath=(~/.zsh $fpath)
# the next two lines are not needed if using oh-my-zsh
autoload -Uz compinit
compinit
附言,
我之前的回答是关于 oh-my-zsh 的插件 gitfast。但它有错误,而且非常过时。