How to use zsh tab completion on Git without origin?

时间:2019-04-16 22:03:42

标签: git ubuntu zsh oh-my-zsh

I am using zsh with oh-my-zsh on Ubuntu 18.04.2. Currently, Git is installed at version 2.20.1.

Whenever I want to push a local branch to a remote (origin) I try to use the tab completion in the shell as follows:

git push origin fea<TAB>

The tab completion results in:

git push origin origin/feature

I cannot push to origin/feature, though. What I actually want is:

git push origin feature

How can I configure the tab completion to correctly (?) complete the remote branch - or am I missing something?

2 个答案:

答案 0 :(得分:3)

经过深入研究,结果发现 oh-my-zsh 不能完成ZSH下git checkout的完成,而是由Shell提供的_git函数来完成设备。

如评论中所述,我无法复制您遇到的问题。一切似乎都按预期进行。不过...

签出以下文件:

/usr/share/zsh/<5.x>/functions/_git

我的本​​地 zsh 版本是 5.2 。在 450 行附近,您可以看到:

  case $state in
    (branch-or-tree-ish-or-file)
      # TODO: Something about *:: brings us here when we complete at "-".  I
      # guess that this makes sense in a way, as we might want to treat it as
      # an argument, but I can't find anything in the documentation about this
      # behavior.
      [[ $line[CURRENT] = -* ]] && return
      if (( CURRENT == 1 )) && [[ -z $opt_args[(I)--] ]]; then
        # TODO: Allow A...B
        local branch_arg='' \
              remote_branch_noprefix_arg='remote branches::__git_remote_branch_names_noprefix' \
              tree_ish_arg='tree-ishs::__git_tree_ishs' \
              file_arg='modified-files::__git_modified_files'

        if [[ -n ${opt_args[(I)-b|-B|--orphan|--detach]} ]]; then
          remote_branch_noprefix_arg=
          file_arg=
        elif [[ -n $opt_args[(I)--track] ]]; then
          branch_arg='remote-branches::__git_remote_branch_names'
          remote_branch_noprefix_arg=
          tree_ish_arg=
          file_arg=
        elif [[ -n ${opt_args[(I)--ours|--theirs|-m|--conflict|--patch]} ]]; then
          remote_branch_noprefix_arg=
        fi

        _alternative \
          $branch_arg \
          $remote_branch_noprefix_arg \
          $tree_ish_arg \
          $file_arg && ret=0

删除传递给_alternative的数组之一会更改在git checkout之后完成分支名称时向您建议的内容。特别是,删除$remote_branch_noprefix_arg会带回前缀为origin的远程分支名称或它们各自的远程存储库名称。

因此,升级您的shell或降级到以前的版本可能是个好主意。

一些细节呢:

  • 我看到您已经编辑了原始帖子,git push有充分的理由与git checkout有所不同;
  • 远程分支的同系物本地分支可能不会强制存在:featureorigin/feature不同,即使前者存在时通常被配置为跟踪后者;
  • 默认情况下,如果本地分支还不存在,并且在没有显式传递选项的情况下,签出feature将创建一个别名本地分支,配置为跟踪远程分支,然后切换到远程分支检出origin/feature将使您进入分离模式,从而可以浏览此远程分支,但直接在其顶部进行提交。

答案 1 :(得分:1)

请注意,自Git 2.23开始,您将使用git switch而不是confusing git checkout

然后...在Git 2.27(2020年第二季度)之前,zsh命令行完成功能对git switch来说不是有效!

请参见commit 051cc54Terry Moschou (tmoschou)(2020年4月17日)。
(由Junio C Hamano -- gitster --commit 7d96ac1中合并,2020年4月28日)

complete:zsh:添加缺少的sub cmd完成候选对象

签名人:Terry Moschou

向zsh完成候选输出中添加缺少的“ restore”和“ switch”子命令。例如

$ git re<tab>
rebase    -- forward-port local commits to the updated upstream head
reset     -- reset current HEAD to the specified state
restore   -- restore working tree files

$ git s<tab>
show      -- show various types of objects
status    -- show the working tree status
switch    -- switch branches

而且,在Git 2.28(2020年第三季度)中,命令行完成(在contrib/中)学会了完成“ git switch”命令所采用的选项。

请参见commit 9143992commit acb658fcommit 00e7bd2commit 6d76a5ccommit 68d97c7commit 4e79adfcommit 6880779,{{3} },commit 58a2ca3commit 0408c6bcommit c81ca56commit 7f59d60commit b07d77acommit c55b99ccommit e69fb0acommit ab58e90( 2020年5月28日)通过commit fab466f
(由Jacob Keller (jacob-keller)Junio C Hamano -- gitster --中合并,2020年6月25日)

示例:

commit 3204218:改进了结帐时对--detach的处理

签名人:Jacob Keller

就像completion一样,如果已指定--detach,则不应填写DWIM远程分支名称。为避免这种情况,以类似于_git_checkout的方式重构_git_switch

请注意,当我们找到dwim_opt-d时,我们不会简单地清除--detach,因为我们将添加其他模式和检查,使此流程更易于遵循。

更新以前失败的测试,以表明破损已得到解决。