刚刚碰到类似的东西;希望可以发布我的笔记。让我对 git 别名和参数感到困惑的一件事可能来自 git help config(我有 git 版本 1.7.9.5):
如果别名扩展以感叹号为前缀,它将被视为 shell 命令。例如定义“alias.new = !gitk --all --not ORIG_HEAD”,调用“git new”相当于运行shell命令
“gitk --all --not ORIG_HEAD”。请注意,shell 命令将从存储库的顶级目录执行,
这可能不一定是当前目录。 [...]
我的看法 - 如果别名“将被视为 shell 命令”时以感叹号为前缀 - 为什么我需要使用函数,或者 sh -c 带参数;为什么不按原样编写我的命令?
我仍然不知道答案 - 但我认为实际上结果略有不同。这是一个小测试 - 将其放入您的 .git/config 或 ~/.gitconfig:
[alias]
# ...
ech = "! echo rem: "
shech = "! sh -c 'echo rem:' "
fech = "! f() { echo rem: ; }; f " # must have ; after echo!
echargs = "! echo 0[[\"$0\"]] 1-\"$1\"/ A-"$@"/ "
fechargs = "! f() { echo 0[[\"$0\"]] 1-\"$1\"/ A-"$@"/ ; }; f "
这是我运行这些别名的结果:
$ git ech word1 word2
rem: word1 word2
$ git shech word1 word2
rem:
$ git fech word1 word2
rem:
$ git echargs word1 word2
0[[ echo 0[["$0"]] 1-"$1"/ A-$@/ ]] 1-word1/ A-word1 word2/ word1 word2
$ git fechargs word1 word2
0[[ f() { echo 0[["$0"]] 1-"$1"/ A-$@/ ; }; f ]] 1-word1/ A-word1 word2/
... 或者:当您在 git 别名中的 ! “原样”之后使用“普通”命令时 - 然后 git 会自动将参数列表附加到该命令!实际上,避免它的一种方法是将脚本作为函数调用 - 或作为 sh -c 的参数。
这里(对我而言)另一件有趣的事情是,在 shell 脚本中,人们通常期望自动变量 $0 是脚本的文件名。但是对于 git 别名函数,$0 参数基本上是指定该命令的 整个 字符串的内容(在配置文件中输入)。
这就是为什么,我猜,如果你碰巧引用错误 - 在下面的情况下,那将是转义外部双引号:
[alias]
# ...
fail = ! \"echo 'A' 'B'\"
... - 然后git 将失败(至少对我而言)有些神秘的信息:
$ git fail
"echo 'A' 'B'": 1: echo 'A' 'B': not found
fatal: While expanding alias 'fail': ' "echo 'A' 'B'"': No such file or directory
我认为,因为git “看到”了整个字符串作为! 的一个参数 - 它试图将其作为可执行文件运行;相应地,它未能找到 "echo 'A' 'B'" 作为文件。
无论如何,在上述git help config 引用的上下文中,我推测这样表述更准确:“ ...调用“git new”相当于运行shell命令“gitk --all --not ORIG_HEAD $@”,其中 $@ 是在运行时从命令行传递给 git 命令别名的参数。...“。我认为这也可以解释为什么 OP 中的“直接”方法不适用于位置参数。