【问题标题】:Disable auto-completion of remote branches in Git Bash?在 Git Bash 中禁用远程分支的自动完成?
【发布时间】:2011-07-08 11:15:01
【问题描述】:

我正在开发一个相当大的 git 存储库,其中包含数千个(远程)分支。我习惯于在控制台(在这种情况下是 Git Bash)中使用自动完成(使用 [TAB]),所以我也无意识地对 git 命令这样做了。

例如我会输入

git checkout task[TAB]

导致控制台经常停顿几分钟。有没有办法将自动完成仅限于本地分支?

【问题讨论】:

  • 注意:自 2011 年以来,您拥有(使用 Git 2.13,2017 年第二季度)git checkout --no-guess ..., or export GIT_COMPLETION_CHECKOUT_NO_GUESS=1:两者都会禁用分支完成。见my answer below

标签: windows git


【解决方案1】:

使用 Git 2.13(2017 年第二季度),您可以禁用(部分)分支完成。

git checkout --no-guess ...
# or:
export GIT_COMPLETION_CHECKOUT_NO_GUESS=1

参见Jeff King (peff)commit 60e71bb(2017 年 4 月 21 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit b439747,2017 年 5 月 1 日)

现在contrib/completion/git-completion.bash 中记录:

您可以设置以下环境变量来影响完成例程的行为:

GIT_COMPLETION_CHECKOUT_NO_GUESS

当设置为“1”时,不要在git-checkout 中包含“DWIM”建议 完成(例如,当“origin/foo”存在时完成“foo”)。

注意:DWIM is short for Do What I Mean,系统试图预测用户打算做什么,自动纠正琐碎的错误,而不是盲目地执行用户明确但可能不正确的输入。

completion:可选择禁用签出 DWIM

当我们完成“git checkout”的分支名称时,我们还完成了可能触发 DWIM 行为的远程分支名称。根据您的工作流程和项目,这可能很方便,也可能很烦人。

例如,我的 gitster.git 克隆包含 74 个本地“jk/*”分支,但 origin 包含另外 147 个。
当我想签出本地分支但记不住名称时,选项卡完成会显示 251 个条目。更糟糕的是,对于一个已经为pu挑的话题,上游分支名称很可能和我的很相似,导致我很可能选错了,不小心创建了一个新的分支。


注意:“picked for pu”:见What's cooking in git.git:开头是:

以'-'为前缀的提交仅在'pu'(建议更新)中,而以'+'为前缀的提交在'next'中。

这是Git Workflow Graduation process 的一部分。

pu(提议的更新)是一个集成分支,用于尚未准备好包含的内容


此补丁为用户添加了一种告知完成的方式 不包含 DWIM 结帐建议的代码。
这可以通过键入来完成:

git checkout --no-guess jk/<TAB>

但这相当麻烦。

当然,缺点是当您确实想要调用 DWIM 行为时,您不再获得完成支持。
但是根据您的工作流程,这可能不会造成很大的损失(例如,在 git.git 中,我更有可能想要分离,所以无论如何我都会输入“git checkout origin/jk/&lt;TAB&gt;”)。

【讨论】:

  • @sehe 我在“pu”部分添加了参考资料和文档。
  • 可悲的是,创建一个在内部使用此选项的别名似乎不起作用。仅在 CLI 上直接提供选项只会导致本地分支完成。 :(
  • 我相信目前最好的解决方案(似乎完全回答了 OP 的要求)是 GIT_COMPLETION_CHECKOUT_NO_GUESS=1,而自 2.23 @VonC 开始使用 git switch
【解决方案2】:

如果您通过自制软件安装了 git-completion,它位于此处: /usr/local/etc/bash_completion.d/git-completion.bash

按照上面的erik.weathers' answer,我进行了以下更改,因此自动完成功能可以根据当前前缀在本地和远程工作。默认情况下,它只会搜索本地,但如果我指定origin/…,它就会知道我也想搜索远程分支。

_git_checkout ()方法中,改变

    __gitcomp_nl "$(__git_refs '' $track)"

到:

    # only search local branches instead of remote branches if origin isn't specified
    if [[ $cur == "origin/"* ]]; then
        __gitcomp_nl "$(__git_refs '' $track)"
    else
        __gitcomp_nl "$(__git_heads '' $track)"
    fi

当然,您可以将 origin 更改为其他名称,或者如果您有超过 1 个,您可以让它通过远程前缀列表搜索。

【讨论】:

  • imo最全的答案
【解决方案3】:

我假设您正在使用git-completion.bash 脚本,并且您关心git checkout

为此,我只是在git-completion.bash 中的_git_checkout () 函数的定义中更改了一行:

<       __gitcomp_nl "$(__git_refs '' $track)"
---
>       __gitcomp_nl "$(__git_heads '' $track)"

我的理解是这只会影响 tab-completion 动作(因为它在 switch-case 语句的* case 中的位置)。

【讨论】:

  • 步骤:sudoedit /usr/share/bash-completion/completions/git,然后更改@erik.weathers 的答案中提到的行,重新打开 bash,瞧!非常感谢。
  • 我同意@andre.orvalho,这绝对是现在更好的解决方案。
  • 我其实加了一个新方法:__git_rco()。 rco(或远程结账)使用 refs 的旧行为。 __git_checkout () 现在只执行heads。我有一个别名 rco = checkout。这样,您仍然可以根据需要获得旧行为。
  • 我添加了一个额外的情况,其中"") 使用__git_heads*) 使用__git_refs。这使得它只建议正面,但如果你已经输入了一些东西(即t),它会给我任何匹配的参考(即tag/sometag)。如果这继续太多,它也可以匹配 tag/ -> tag/sometags 等。
  • 如果你通过 brew 安装了 git-completion,它位于:/usr/local/etc/bash_completion.d/git-completion.bash
【解决方案4】:

Carey Metcalfe 写了a blog post,其中包含一个解决方案,该解决方案还可以编辑自动完成功能,但代码比其他答案稍新。他还定义了一个别名checkoutr,以保留旧的自动完成行为以备不时之需。

简而言之,首先使用以下命令创建 checkoutr 别名:

git config --global alias.checkoutr checkout

然后找到git-completion.bash,将_git_checkout 函数复制到你的shell 的RC 文件中,以便重新定义它,然后在该函数中,替换这一行:

__git_complete_refs $track_opt

以下几行:

if [ "$command" = "checkoutr" ]; then
    __git_complete_refs $track_opt
else
    __gitcomp_direct "$(__git_heads "" "$cur" " ")"
fi

有关更多详细信息和代码的潜在更新,请参阅the blog post

【讨论】:

    【解决方案5】:

    你可以破解 /etc/bash_completion.d/git

    您需要编辑__git_refs ()

    请注意,行为的变化将适用于每个地方(因此即使使用 git push/pull 可能你不希望它出现)。当然,您可以复制该函数或传递一个额外的参数,但我将其留给您

    【讨论】:

    • 是的,事实证明标签 远程分支很慢。我将refs="refs/tags refs/heads refs/remotes" 更改为仅refs="refs/heads" 并注释掉了整个“尝试查找与完成字匹配的远程分支”部分。不漂亮,但 WFM :-)
    • 嗯。您没有机会通过网络使用 git 存储库吗?我从未见过 那种可悲的 git 性能(但是:git add 在 Windows 中是出了名的慢)
    • 不,我在本地使用 git。我猜这只是一个巨大的回购。 git for-each-ref | wc -l 返回 11000 ...
    • 但是是的,Git 在 Windows 上明显比在 *nix/Mac 上慢。
    • 知道如何为 zsh 执行此操作吗?
    【解决方案6】:

    您可以认为您只是别名为 co 的本地分支和带有完整命令 checkout 的所有分支。

    您可以执行以下操作。在您的 .bashrc 中,您重新定义了 _git_checkout() 函数。你让这个函数保持不变,除了结尾:

    if [ $command -eq "co" ]; then
      __gitcomp "$(__git_refs_local '' $track)"
    else
      __gitcomp "$(__git_refs '' $track)"
    fi
    

    然后,您只需定义一个新函数 __git_refs_local,您可以在其中删除远程内容。

    【讨论】:

    • -eq 用于比较数字,比较应该是if [ $command = "co" ]; then
    【解决方案7】:

    修改$(brew --prefix)/etc/bash_completion.d/git-completion.bash 不是一个好主意,因为每次通过 Homebrew 更新 Git 时它都会被覆盖。

    在获取完成文件后,结合我在.bash_profile 中的完成文件中仅覆盖_git_checkout 函数的所有答案:

    _git_checkout ()
    {
      __git_has_doubledash && return
    
      case "$cur" in
        --conflict=*)
          __gitcomp "diff3 merge" "" "${cur##--conflict=}"
          ;;
        --*)
          __gitcomp "
          --quiet --ours --theirs --track --no-track --merge
          --conflict= --orphan --patch
          "
          ;;
        *)
          # 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
          # only search local branches instead of remote branches if origin isn't
          # specified
          if [[ $cur == "origin/"* ]]; then
            __gitcomp_nl "$(__git_refs '' $track)"
          else
            __gitcomp_nl "$(__git_heads '' $track)"
          fi
          ;;
      esac
    }
    

    【讨论】:

      【解决方案8】:

      我自己没有使用 Git Bash,但如果这与中提到的相同 http://tekrat.com/2008/04/30/bash-autocompletion-git-super-lazy-goodness/,你应该可以用普通的 git branch in

      替换 git branch -a
      _complete_git() {
        if [ -d .git ]; then
          branches=`git branch -a | cut -c 3-`
          tags=`git tag`
          cur="${COMP_WORDS[COMP_CWORD]}"
          COMPREPLY=( $(compgen -W "${branches} ${tags}" -- ${cur}) )
        fi
      }
      complete -F _complete_git git checkout
      

      (在您的 .profile 或类似文件中)并获得您想要的。

      【讨论】:

      • 嗯。此功能将是标准 Git 行为的补充(至少我在任何地方都没有该功能)。我想要做的比默认的少。编辑 __git_refs() 似乎可以解决问题。
      【解决方案9】:

      这里的 FWW 是对 __git_complete_refs 的破解,可以解决问题

      __git_complete_refs ()
      

      { 本地远程跟踪 pfx cur_="$cur" sfx=""

      while test $# != 0; do
          case "$1" in
          --remote=*) remote="${1##--remote=}" ;;
          --track)    track="yes" ;;
          --pfx=*)    pfx="${1##--pfx=}" ;;
          --cur=*)    cur_="${1##--cur=}" ;;
          --sfx=*)    sfx="${1##--sfx=}" ;;
          *)      return 1 ;;
          esac
          shift
      done
      echo cur_ $cur_ > a
       if [[  $GIT_COMPLETION_CHECKOUT_NO_GUESS != 1 || $cur_ == "origin"* ]]; then
          __gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")"
        else
          __gitcomp_direct "$(__git_heads  "" "$cur_")"
        fi
      

      }

      【讨论】:

        猜你喜欢
        • 2011-08-30
        • 1970-01-01
        • 2012-04-09
        • 2016-08-16
        • 2016-02-03
        • 2012-03-01
        • 2018-07-17
        • 2020-12-25
        • 2012-10-22
        相关资源
        最近更新 更多