简体   繁体   English

在 Git Bash 中禁用远程分支的自动完成?

[英]Disable auto-completion of remote branches in Git Bash?

I'm working on a fairly large git repo with a couple of thousand (remote) branches.我正在开发一个相当大的 git 存储库,其中包含数千个(远程)分支。 I am used to using auto-completion (using [TAB]) in the console (Git Bash in that case), so I unconsciously do that for git commands, too.我习惯于在控制台中使用自动完成(使用 [TAB])(在这种情况下是 Git Bash),所以我也无意识地对 git 命令这样做了。

eg I'd type例如,我会输入

git checkout task[TAB]

with the effect that the console stalls for often minutes.效果是控制台经常停顿几分钟。 Is there a way to limit auto-completion to local branches only?有没有办法将自动完成限制在本地分支机构?

With Git 2.13 (Q2 2017), you can disable (some of) the branch completion.使用 Git 2.13(2017 年第二季度),您可以禁用(部分)分支完成。

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

See commit 60e71bb (21 Apr 2017) by Jeff King ( peff ) .请参阅Jeff King ( peff )提交 60e71bb (2017 年 4 月 21 日)。
(Merged by Junio C Hamano -- gitster -- in commit b439747 , 01 May 2017) (由Junio C Hamano -- gitster --提交 b439747中合并,2017 年 5 月 1 日)

As documented in contrib/completion/git-completion.bash now:contrib/completion/git-completion.bash中所述:

You can set the following environment variables to influence the behavior of the completion routines:您可以设置以下环境变量来影响完成例程的行为:

 GIT_COMPLETION_CHECKOUT_NO_GUESS

When set to "1", do not include "DWIM" suggestions in git-checkout completion (eg, completing "foo" when "origin/foo" exists).当设置为“1”时,不要在git-checkout完成中包含“DWIM”建议(例如,当“origin/foo”存在时完成“foo”)。

Note: DWIM is short for D o W hat I M ean , where a system attempts to anticipate what users intend to do, correcting trivial errors automatically rather than blindly executing users' explicit but potentially incorrect inputs.注意: DWIMD o W hat I Mean 的缩写,系统试图预测用户打算做什么,自动纠正微不足道的错误,而不是盲目地执行用户显式但可能不正确的输入。

completion : optionally disable checkout DWIM completion :可选择禁用结帐 DWIM

When we complete branch names for " git checkout ", we also complete remote branch names that could trigger the DWIM behavior.当我们完成“ git checkout ”的分支名称时,我们还完成了可能触发 DWIM 行为的远程分支名称。 Depending on your workflow and project, this can be either convenient or annoying.根据您的工作流程和项目,这可能很方便,也可能很烦人。

For instance, my clone of gitster.git contains 74 local " jk/* " branches, but origin contains another 147.例如,我的gitster.git克隆包含 74 个本地“ jk/* ”分支,但 origin 包含另外 147 个。
When I want to checkout a local branch but can't quite remember the name, tab completion shows me 251 entries.当我想签出一个本地分支但记不住名称时,选项卡完成会显示 251 个条目。 And worse, for a topic that has been picked up for pu, the upstream branch name is likely to be similar to mine, leading to a high probability that I pick the wrong one and accidentally create a new branch.更糟糕的是,对于一个已经为 pu 挑出来的话题,上游分支名称很可能和我的很相似,导致我很可能选错了,不小心创建了一个新的分支。


Note: "picked up for pu": see a What's cooking in git.git : it starts with:注意:“pick up for pu”:请参阅git.git中的烹饪内容:它以:

Commits prefixed with ' - ' are only in ' pu ' (proposed updates) while commits prefixed with ' + ' are in ' next '.以“ - ”为前缀的提交仅在pu ”(建议的更新)中,而以“ + ”为前缀的提交在“ next ”中。

This is part of the Git Workflow Graduation process .这是Git 工作流毕业过程的一部分。

pu (proposed updates) is an integration branch for things that are not quite ready for inclusion yet pu (提议的更新)是一个集成分支,用于尚未准备好包含的内容


This patch adds a way for the user to tell the completion code not to include DWIM suggestions for checkout.此补丁为用户添加了一种方法来告诉完成代码不要包含 DWIM 结帐建议。
This can already be done by typing:这已经可以通过键入:

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

but that's rather cumbersome.但这很麻烦。

The downside, of course, is that you no longer get completion support when you do want to invoke the DWIM behavior.当然,缺点是当您确实想要调用 DWIM 行为时,您不再获得完成支持。
But depending on your workflow, that may not be a big loss (for instance, in git.git I am much more likely to want to detach, so I'd type " git checkout origin/jk/<TAB> " anyway).但是根据您的工作流程,这可能不是一个很大的损失(例如,在 git.git 中,我更有可能想要分离,所以我会键入“ git checkout origin/jk/<TAB> ”检查。

I'm assuming that you are using the git-completion.bash script, and that you only care about git checkout .我假设您使用的是git-completion.bash脚本,并且您关心git checkout

To accomplish this, I just changed one line in the definition of the _git_checkout () function in git-completion.bash :为此,我只是在git-completion.bash中的_git_checkout () function 的定义中更改了一行:

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

My understanding is that this only affects the tab-completion action (because of its location within the * case of the switch-case statement).我的理解是,这只会影响 tab-completion 操作(因为它在 switch-case 语句的* case 中的位置)。

You can hack /etc/bash_completion.d/git你可以破解 /etc/bash_completion.d/git

You'll need to edit __git_refs ()您需要编辑__git_refs ()

Note that the change in behaviour will apply every where (so even with git push/pull where you might not want it to).请注意,行为的变化将适用于所有地方(因此即使在您可能不希望的地方使用 git 推/拉)。 You could of course, make a copy of the function or pass an extra parameter, but I leave that to you当然,您可以复制 function 或传递一个额外的参数,但我将其留给您

If you installed git-completion via homebrew, it's located here: /usr/local/etc/bash_completion.d/git-completion.bash如果您通过自制软件安装了 git-completion,它位于: /usr/local/etc/bash_completion.d/git-completion.bash

Following erik.weathers' answer above, I made the following change so autocompletion can work for both local and remote based on the current prefix.按照上面erik.weathers 的回答,我进行了以下更改,以便自动完成功能可以根据当前前缀在本地和远程工作。 By default, it'll only search local, but if I specify origin/… it'll know I want to search remote branches too.默认情况下,它只会搜索本地,但如果我指定origin/…它会知道我也想搜索远程分支。

In the _git_checkout () method, change_git_checkout ()方法中,更改

    __gitcomp_nl "$(__git_refs '' $track)"

to:至:

    # 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

Of course, you can change origin to something else or you can have it search through through a list of remote prefixes if you have more than 1.当然,您可以将origin更改为其他内容,或者如果您有超过 1 个,您可以让它通过远程前缀列表进行搜索。

You could think that you just the local branches with the alias co and all the branches with the complete command checkout .您可以认为您只是具有别名co的本地分支和具有完整命令checkout的所有分支。

You could perform the following.您可以执行以下操作。 In your.bashrc, you redefine the _git_checkout() function.在 your.bashrc 中,重新定义_git_checkout() function。 You let this function unchanged, except the end:你让这个 function 不变,除了结尾:

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

Then, you just have to define a new function, __git_refs_local , where you remove the remote stuff.然后,您只需要定义一个新的 function, __git_refs_local ,在其中删除远程内容。

Carey Metcalfe wrote a blog post containing a solution that also edits the auto-completion function, but with slightly newer code than other answers. Carey Metcalfe 写了一篇博客文章,其中包含一个解决方案,该解决方案还编辑了自动完成 function,但代码比其他答案稍新。 He also defines an alias checkoutr that keeps the old auto-complete behavior in case it's ever needed.他还定义了一个别名checkoutr ,以保留旧的自动完成行为,以备不时之需。

In short, first create the checkoutr alias with this command:简而言之,首先使用以下命令创建checkoutr别名:

git config --global alias.checkoutr checkout

Then find git-completion.bash , copy the _git_checkout function into your shell's RC file so that it gets redefined, and inside that function, replace this line:然后找到git-completion.bash ,将_git_checkout function 复制到 shell 的 RC 文件中,以便重新定义它,然后在 ZC1C425268E68385D1AB50741C 中替换此行:

__git_complete_refs $track_opt

with the following lines:使用以下几行:

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

See the blog post for more details and potential updates to the code.有关代码的更多详细信息和潜在更新,请参阅博客文章

Modifying $(brew --prefix)/etc/bash_completion.d/git-completion.bash is not a good idea because it will be overwritten every time you update Git through Homebrew.修改$(brew --prefix)/etc/bash_completion.d/git-completion.bash不是一个好主意,因为每次通过 Homebrew 更新 Git 时都会覆盖它。

Combining all the answers I overwrite only _git_checkout function from the completion file in my .bash_profile after sourcing the completion file:结合所有答案,我在采购完成文件后仅覆盖.bash_profile中的完成文件中的_git_checkout function :

_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
}

FWW here is a hack to __git_complete_refs that does the trick FWW 这里是对 __git_complete_refs 的破解,它可以解决问题

__git_complete_refs ()

{ local remote track pfx cur_="$cur" sfx=" " { 本地远程跟踪 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

} }

I'm not using Git Bash myself, but if this is the same as mentioned in http://tekrat.com/2008/04/30/bash-autocompletion-git-super-lazy-goodness/ , you should be able to replace git branch -a with a plain git branch in I'm not using Git Bash myself, but if this is the same as mentioned in http://tekrat.com/2008/04/30/bash-autocompletion-git-super-lazy-goodness/ , you should be able to用普通的git 分支替换 git分支 -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

(in your.profile or similar) and get what you want. (在 your.profile 或类似文件中)并得到你想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM