34

如果我运行一个常规的 git 命令,例如当git checkout我按下 tab 键时,我会得到有用的分支名称自动补全。

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

编辑:

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

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
4

2 回答 2

37

对于 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().

于 2012-07-13T11:08:15.593 回答
4

2015 年 7 月更新 (Git 2.5):在contrib/completion/git-completion.bash.

请参阅SZEDER Gábor ( )的commit 12bdc88commit e8f9e42(2015 年 5 月 10 日) 。(由Junio C Hamano 合并 -- --提交 935d937中,2015 年 5 月 22 日)szeder
gitster

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

Git 补全应该在 Git 2.1(2014 年 8 月)中更好地处理复杂别名。
请参阅Steffen Prohaska的提交 56f24e8 ( )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 () ...' 都可以工作。

于 2014-08-02T20:18:02.320 回答