为什么引用参数在 git 别名中不起作用? [英] Why does quoting arguments not do anything in git aliases?
问题描述
我有以下 ~/.gitconfig
:
[alias]
print = !printf %s\\\\n a b c
它的行为如下:
$ git print
a
b
c
但是现在我把它改成下面的~/.gitconfig
:
But now I change it to the following ~/.gitconfig
:
[alias]
print = !printf %s\\\\n "a b" c
然而 a
和 b
仍然进行分词:
and yet the a
and b
still undergo word splitting:
$ git print
a
b
c
如果 ""
引号不能防止分词,那么它们在做什么?
命令是如何解析的?
If the ""
quotes aren't preventing word-splitting then what are they doing?
How are the commands parsed?
推荐答案
Git 的配置语言解析器 出于自身目的使用双引号:
Git's configuration-language parser uses double quotes for its own purposes:
... Doublequote "
和反斜杠可以通过将它们分别转义为 \"
和 \\
来包含在内.读取时删除其他字符前面的反斜杠;例如,\t
读作 t
而 \0
读作 0
...
... Doublequote
"
and backslash can be included by escaping them as\"
and\\
, respectively. Backslashes preceding other characters are dropped when reading; for example,\t
is read ast
and\0
is read as0
...
当这个特定的段落讨论小节名称时,双引号和双反斜杠规则也适用于小节名称之外.这些引号的其余部分适用于任何地方,除了小节名称中的 \t
=t
类型:
While this particular paragraph is discussing subsection names, the double-quote and double-backslash rules apply outside subsection names as well. The rest of these quotes apply everywhere, except for the \t
=t
kind of thing in subsection names:
在双引号内,双引号 "
和反斜杠 \
字符必须转义:使用 \"
for ";
和 \\
用于 \
.
Inside double quotes, double quote
"
and backslash\
characters must be escaped: use\"
for"
and\\
for\
.
可以识别以下转义序列(在 \"
和 \\
旁边): \n
用于换行符 (NL),\t
用于水平制表(HT,TAB)和 \b
用于退格(BS).其他字符转义序列(包括八进制转义序列)无效.
The following escape sequences (beside \"
and \\
) are recognized: \n
for newline character (NL), \t
for horizontal tabulation (HT, TAB) and \b
for backspace (BS). Other char escape sequences (including octal escape sequences) are invalid.
请注意,这些都与别名没有任何关系:这些规则适用于 .gitconfig
或 中的所有行>.git/config
文件.(这在例如子模块路径中很重要,尽管通常不会编码一个双引号.)
Note that none of this has anything to do with aliases specifically: these rules apply to all lines in a .gitconfig
or .git/config
file. (This matters in, e.g., submodule paths, though one wouldn't generally encode a double quote in one.)
现在,在配置解析器完成读取.git/config
文件后,如果该行在alias
部分,它定义别名.在该别名中,双引号确实可以防止分词:
Now, after the configuration parser is done reading the .git/config
file, if the line is in an alias
section, it defines an alias. Within that alias, double quotes do prevent word-splitting:
[alias]
foo = log \"a b\"
$ git foo
fatal: ambiguous argument 'a b': unknown revision or path not in the working tree.
请注意,首先要通过配置解析器,这些必须用反斜杠给出.为了避免这种特殊的烦恼,我们可以改用单引号:
Note that to get past the configuration parser in the first place, these had to be given with backslashes. To avoid that particular annoyance we can use single quotes instead:
[alias]
foo = log 'a b'
产生相同的结果.
如果别名是 shell 别名(以 !
为前缀),则整个字符串(当然不包括感叹号)将被馈送到 shell.要观察这一点,请使用 GIT_TRACE
:
If the alias is a shell alias (prefixed with !
), the entire string (minus the exclamation point of course) is fed to the shell. To observe that, use GIT_TRACE
:
[alias]
foo = !printf %s\\\\n 'a b'
$ GIT_TRACE=1 git foo
23:15:46.947801 git.c:670 trace: exec: git-foo
23:15:46.948153 run-command.c:643 trace: run_command: git-foo
23:15:46.948883 run-command.c:643 trace: run_command: 'printf %s\\n '\''a b'\'''
a b
如果我们在配置解析器后面得到双引号,它们的效果是一样的:
If we get double quotes past the configuration parser, they have the same effect:
$ GIT_TRACE=1 git foo
23:16:24.919042 git.c:670 trace: exec: git-foo
23:16:24.919402 run-command.c:643 trace: run_command: git-foo
23:16:24.920114 run-command.c:643 trace: run_command: 'printf %s\\n "a b"'
a b
我们需要四个反斜杠的原因当然是,Git 配置解析器将它们变成了两个反斜杠(如 GIT_TRACE=1
输出所示),然后 shell 本身将它们变成了一个反斜杠,其中 printf
与 n
组合以形成换行符.
The reason we need four backslashes is, of course, that the Git configuration parser turned them into two backslashes (as shown in the GIT_TRACE=1
output) and the shell itself then turned them into one backslash, which printf
combined with the n
to make a newline.
尝试别名:
foo = !printf %s\\\\n "a b
失败:
fatal: bad config line 30 in file [path]/.gitconfig
因为 Git 本身正在运行其逐行解析器并且对未关闭的引用不满意.
because Git itself is running its line-by-line parser and is unhappy with the unclosed quote.
这篇关于为什么引用参数在 git 别名中不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!