【问题标题】:Git aliases - command line autocompletion of branch namesGit 别名 - 分支名称的命令行自动补全
【发布时间】:2012-07-13 02:21:02
【问题描述】:

如果我运行诸如git checkout 之类的常规 git 命令,我会在按 Tab 键时获得有用的分支名称自动补全。

我有一些 git 别名,它们将分支名称作为参数,我想知道是否有办法让分支名称自动完成以与它们一起使用?

编辑:

只是为了从 cmets 中的讨论中提供一些澄清,具有直接映射的别名可以正常工作,即:

ci = commit
co = checkout

它涉及更多一点,并使用$1作为参数而不是,例如:

tagarchive = !f() { git tag archive/$1 origin/$1 && git push origin :$1 && git push origin archive/$1 && git branch -d $1; }; f

【问题讨论】:

  • 自动完成对我来说确实适用于别名。你在使用 bash 吗?你在什么系统上? (操作系统、发行版、包管理器等)只是检查,但“git 别名”是指名为 alias.foo 的 git config 条目,对吗?
  • @kini bash 在 Ubuntu 上。 Git 别名存储在配置中的[alias] 中,是的。
  • 你能告诉我们这些别名吗?例如,我为checkoutwhatchanged 提供了简单的重命名别名,这些别名仍然适用于制表符完成(这也适用于 Ubuntu,值得一提)。
  • @David 这说明了这一点——我也有一些重命名别名——我怀疑当别名的作用不仅仅是直接映射时,自动完成功能会停止工作。 co (checkout) 之类的别名对我来说很好用。更新了问题。
  • Git 补全应该在 Git 2.1(2014 年 8 月)中更好地工作。见my answer below

标签: linux git autocomplete alias


【解决方案1】:

对于 git 别名,git 命令 (__git()) 的自动完成功能使用对 git config --get "alias.$1" 的调用来确定等效的自动完成功能。这适用于简单的映射,但会阻塞更复杂的别名。

要解决此问题,请定义一个名称与您的别名匹配的自动完成函数,即_git_tagarchive()。 git 的自动完成功能应该选择它并将其用于自动完成。

例如:

[me@home]$ git tagarchive <TAB><TAB>
AUTHORS             gentleSelect/       .gitignore          LICENSE             test_multiple.html  
cron/               .git/               index.html          README.md  
[me@home]$ _git_tagarchive() {
> _git_branch  # reuse that of git branch
> }
[me@home]$ git tagarchive  <TAB><TAB>
enable_multiple          master                   origin/gh-pages          v0.1                     v0.1.3 
FETCH_HEAD               ORIG_HEAD                origin/HEAD              v0.1.1                   v0.1.3.1 
HEAD                     origin/enable_multiple   origin/master            v0.1.2 

要获得更持久的解决方案,只需将函数定义添加到您的 bashrc 文件中。例如:

_git_tagarchive() 
{
    _git_branch
}

请注意,我只是为git branch 重用了自动完成功能;您可能希望将其更改为更合适的内容或编写您自己的内容。

更多信息

此解决方案是根据对 /etc/bash_completion.d/git 的探索确定的。

通常,别名 git 命令由 __git_aliased_commands() 函数处理,该函数解析 git config --get "alias.$1" 的输出以决定要使用的自动完成函数。可以理解,使用更复杂的 shell 命令作为别名目标会挫败这种方法。

进一步看,通过简单地在函数前面加上_git_(命令中的破折号(-)被下划线代替),它似乎在子命令的自动完成功能中出现了git(_git())链的自动完成功能。这是在检查__git_aliased_command() 之前完成的,因此我们可以使用它。

_git ()
{ 
   # .....
   local completion_func="_git_${command//-/_}"
   declare -f $completion_func >/dev/null && $completion_func && return

   local expansion=$(__git_aliased_command "$command")
   if [ -n "$expansion" ]; then
       completion_func="_git_${expansion//-/_}"
       declare -f $completion_func >/dev/null && $completion_func
   fi

}

因此,我采用的方法是确保存在与您的别名匹配的函数,即_git_tagarchive()

【讨论】:

  • 这很好,感谢您的深入解释。
  • 是否可以在提供的函数中禁用某些 comp-options(我不希望它使用默认的文件名完成)?
【解决方案2】:

2015 年 7 月更新 (Git 2.5):在 contrib/completion/git-completion.bash 中获取 git 别名更容易。

commit 12bdc88commit e8f9e42(2015 年 5 月 10 日)SZEDER Gábor (szeder)
(由 Junio C Hamano -- gitster -- 合并到 commit 935d937,2015 年 5 月 22 日)

~~~~~~~~~~~~~~

Git 补全应该在 Git 2.1(2014 年 8 月)中更好地处理复杂别名。
commit 56f24e8Steffen Prohaska (sprohaska)

完成:处理“!f() { ... }; f”和“!sh -c '...' -”别名

'!f() { ... }; f' 和 "!sh -c '....' -" 是用于声明更复杂别名的推荐模式(请参阅git wiki)。
这个提交教导完成来处理它们。

在确定别名使用哪个补全时,现在会跳过左大括号或单引号,并继续搜索 git 命令。
例如,别名“!f() { git commit ... }”或“!sh -c 'git commit ...'”现在会触发提交完成。
以前,搜索停止在左大括号或引号上,并尝试完成 它来决定如何完成,这显然是没有用的。

null 命令“:”现在已被跳过,因此它可以用作声明所需完成样式的解决方法。

例如别名:

!f() { : git commit ; if ... } f
!sh -c ': git commit; if ...' -

现在触发提交完成。

Shell 函数声明现在可以在括号前使用或不使用空格,即“!f() ...”和“!f () ...”都可以使用。

【讨论】:

  • 对于使用 git v2.17.1 的我来说,这并不是那么简单。我不能以任何方式(甚至转义)在别名的值中使用; char。我最终改用 &amp;&amp; - 不同的含义,但实际上与 null 命令的组合没有区别。
猜你喜欢
  • 1970-01-01
  • 2017-05-09
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 2015-11-28
  • 2022-01-19
  • 1970-01-01
  • 2019-08-11
相关资源
最近更新 更多