如何为 git 命令编写包装函数

如何为 git 命令编写包装函数

我想为 git log 创建一个特殊的别名,以便当我使用它时,它会使用--graph--pretty标记自定义的漂亮格式。

我知道我可以使用 git 别名,但我不想这样做,因为我想让它动态化,这样它也可以接受额外的参数/标志。另外,我想了解 bash 中的包装工作原理,所以我想尝试一下。

所以这就是我想要它做的事情;

当我使用

git log spc
         ^_______(custom argument)

它运行如下

git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset %C(grey)(%cr) ' --abbrev-commit --date=relative

因此为此,我添加了此命令(从这个答案) 在我的~/.bash_profile

## git wrapper
git()
{
  if [ $# -gt 0 ] && [ "$1" == "log" ] && [ "$2" == "spc" ]; then
     shift
     set -x
     command git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset %Cgreen(%cr) ' --abbrev-commit --date=relative "$@"
  else
     command git log "$@"
  fi
}

但它不起作用,这是我得到的错误

+ git log spc
+ '[' 2 -gt 0 ']'
+ '[' log == log ']'
+ '[' spc == spc ']'
+ shift
+ command git log --graph '--pretty=format:%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset %Cgreen(%cr) ' --abbrev-commit --date=relative spc
+ git log --graph '--pretty=format:%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset %Cgreen(%cr) ' --abbrev-commit --date=relative spc
fatal: ambiguous argument 'spc': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
++ printf '\033]0;%s@%s:%s\007' aman ip-xx-x-xx-xx '~/one-xx-aws'

答案1

它附加spc到命令:您可以在错误输出中的第 6 行和第 7 行看到它写入... --abbrev-commit --date=relative spc

我认为这是由于"@"你的函数块中的部分if。也许你可以跳过第一个参数(spc)和仅包含第二个及以后的参数通过使用"${@:2}"而不是"@"

 command git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset %Cgreen(%cr) ' --abbrev-commit --date=relative "${@:2}"

答案2

总结

使用shift 2代替shift并删除分支log中的else


在你的包装函数中

## git wrapper
git()
{
  if [ $# -gt 0 ] && [ "$1" == "log" ] && [ "$2" == "spc" ]; then
     shift    # **********************************************************
     set -x  
     command git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset %Cgreen(%cr) ' --abbrev-commit --date=relative "$@"
  else
     command git log "$@"
  fi
}

shift如果前两个命令行参数匹配log,则使用spc。这将删除第一个参数log,但不会删除第二个参数spc。将spc作为 的一部分附加到命令行中"@"。这会导致错误的命令

git log --graph  ...  --date=relative spc

最后git抱怨的是什么。spc

正如所写Saaru Lindestøkke 的回答,您可以使用"${@:2}"而不是"@"从列表中删除一个参数。

shift对我来说,使用两种不同的方法(和"${@:2}")删除第一个和第二个参数是没有意义的。我建议将shift 2(或两次shift)与原始行结合使用command git ...

log此外,我假设当命令行参数不是log和时,您不想插入额外的参数spc。这就是为什么我删除了分支log中的else

修改后的代码:

## git wrapper
git()
{
  if [ $# -gt 0 ] && [ "$1" == "log" ] && [ "$2" == "spc" ]; then
     shift 2
     command git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset %Cgreen(%cr) ' --abbrev-commit --date=relative "$@"
  else
     command git "$@"
  fi
}

请注意shift适用于每个 POSIX 兼容 shell。bash您也可以使用"${@:3}"并省略shift

答案3

考虑到它的作用,您的方法太复杂了。我认为自定义 Bash 函数或自定义脚本对于完全适合 Git 别名的用例来说有点太多了。但包装git 不止于此。

我知道我可以使用 git 别名,但是我不想这样做,因为我想使它动态化,以便它也可以接受额外的参数/标志。

您的包装器传递了"$@",这意味着您可以传递额外的git log标志/开关。但 git 别名允许您做同样的事情。

git config --add --global alias.logcustom "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset %Cgreen(%cr) ' --abbrev-commit --date=relative"

现在你可以将它与其他开关一起使用。例如限制为五次提交:

git logcustom -5

或者打印差异:

git logcustom -p

相关内容