如何使 Git 别名的制表符补全像现有命令一样?



我正在编写一个 shell 脚本来向 git 添加一个"review"子命令,以便更轻松地进行代码审查。它基本上是一个用于git diffgit difftool命令的花哨包装器,但需要较少的键入。

一些示例用法:

# Lists added, deleted, renamed and modified files between master and current branch
git review master -l
# Opens difftool for files modified between master and current branch
git review -m

我想在我的 shell 脚本中启用分支自动完成,但终生无法弄清楚如何做到这一点。这是我真正想要的:

git review ma<tab><tab>

然后它应该表现得像git checkout ma<tab><tab>.

我的外壳脚本:

#!/bin/env bash
function print_usage {
echo "Usage: git review <branch> <-a|-d|-m|-l> [-- paths/to filter/by]"
echo ""
echo "    -a: Only review added files"
echo "    -d: Only review delete files"
echo "    -m: Only review modified files"
echo "    -l: List files and and type of modification"
}
if [ -z "$1" ] || [ -z "$2" ]; then
print_usage
exit 1
fi
git_branch=$1
review_command=$2
path_filters=""
shift
shift
if [ "$1" = "--" ]; then
path_filters="$@"
fi
case $review_command in
"-a")
echo "Reviewing added files..."
if [ -z "$path_filters" ]; then
git difftool $git_branch -- $(git diff --name-status $git_branch | grep -E '^A' | awk '{print $2}')
else
git difftool $git_branch -- $(git diff --name-status $git_branch -- $path_filters | grep -E '^A' | awk '{print $2}')
fi
;;
"-d")
echo "Reviewing deleted files..."
if [ -z "$path_filters" ]; then
git difftool $git_branch -- $(git diff --name-status $git_branch | grep -E '^D' | awk '{print $2}')
else
git difftool $git_branch -- $(git diff --name-status $git_branch -- $path_filters | grep -E '^D' | awk '{print $2}')
fi
;;
"-m")
echo "Reviewing modified files..."
if [ -z "$path_filters" ]; then
git difftool $git_branch -- $(git diff --name-status $git_branch | grep -E '^M' | awk '{print $2}')
else
git difftool $git_branch -- $(git diff --name-status $git_branch -- $path_filters | grep -E '^M' | awk '{print $2}')
fi
;;
"-l")
echo "Differences between $git_branch and $(git mybranch)..."
if [ -z "$path_filters" ]; then
git diff --name-status $git_branch
else
git diff --name-status $git_branch -- $path_filters
fi
;;
esac
echo ""
echo "Review finished."

真的,由于我正在输入命令,我怀疑我的 shell 脚本是否与解决方案有任何关系。

其他一些有用的信息:

  • 视窗 10
  • Git v2.18.0.windows.1
  • 外壳:GNU bash,版本 4.4.19(2(-release (x86_64-pc-msys(

有没有办法将 git 分支自动完成添加到自定义 git 扩展命令中?


Linux 的一个有趣的相关问题:自定义 git 命令自动完成。

使用别名

让我们假设脚本的最小版本,类似于

#!/usr/bin/env bash
git diff "$@"

这是可执行的,并且在您的$PATH中的某个地方。我们称之为gitreview.

要获取它的别名,您可以在.gitconfig中添加如下:

[alias]
review = "!f() { gitreview "$@"; }; f"

当您输入git时,这将使您完成review。现在,要使其行为与git checkout相同,您可以使用 null 命令,如下所示:

review = "!f() { : git checkout ; gitreview "$@"; }; f"

它将完成与git checkout相同的完成!请注意,checkout;之间的空白是必需的。


这在git-completion.bash的评论中提到:

# If you use complex aliases of form '!f() { ... }; f', you can use the null
# command ':' as the first command in the function body to declare the desired
# completion style.  For example '!f() { : git commit ; ... }; f' will
# tell the completion to use commit completion.  This also works with aliases
# of form "!sh -c '...'".  For example, "!sh -c ': git commit ; ... '".

使用外部命令

或者,您可以通过将脚本命名为git-review并将其保留在$PATH中的某个位置来使脚本成为适当的外部命令。要完成它(假设您同时完成 Bash 和 Git 完成(,请将其添加到您的~/.bash_completion文件中(如果它不存在,只需创建它(:

_git_review() { _git_checkout; }

Git 完成(对于 Git 2.18 或更高版本(检查名为_git_$command的完成函数,通过这样做,您可以说"只需调用_git_checkout即可"。

最新更新