Git 配置别名转义

Posted

技术标签:

【中文标题】Git 配置别名转义【英文标题】:Git config alias escaping 【发布时间】:2016-10-29 15:53:59 【问题描述】:

我正在尝试编写一个 git 别名,该别名从提交消息中删除字符串“[ci skip]”(位于消息末尾),但我在转义时遇到问题。别名从作为参数传递给HEAD 的提交中获取所有提交。

如果我运行以下命令:

git filter-branch -f --msg-filter "sed -e \"s/\[ci skip\]$//g\"" master..HEAD

它按预期工作。无论如何,如果我创建以下别名:

unwip = !sh -c 'git filter-branch -f --msg-filter \"sed -e \\\"s/\[ci skip\]$//g\\\"\" $0..HEAD'

我运行git unwip master 它抱怨配置错误,但我希望它表现得像以前的逗号。我该如何解决这个问题?

【问题讨论】:

只是猜测:也许还可以通过像 \\\[ci skip\\\] 这样的额外转义反斜杠来屏蔽转义方括号的反斜杠? @Dilettant 不幸无法正常工作。 【参考方案1】:

通用解决方案

git 别名正确传递解析器可能是一组令人难以置信的\\\\" 噪音,所以我创建了两个别名:

# Quote / unquote a sh command, converting it to / from a git alias string
quote-string = "!read -r l; printf \\\"!; printf %s \"$l\" | sed 's/\\([\\\"]\\)/\\\\\\1/g'; printf \" #\\\"\\n\" #"
quote-string-undo = "!read -r l; printf %s \"$l\" | sed 's/\\\\\\([\\\"]\\)/\\1/g'; printf \"\\n\" #"

这允许您将任何可以输入的内容转换为sh+,例如:

$ echo '\"'

\"

放入适合别名的带引号的字符串:

$ git quote-string
echo '\"'

"!echo '\\\"' #"

为了引用一个多行字符串,我写了一个更长的script,我建议你这样运行:

git quote-string |sponge

回答 OP 的具体问题

在 OP 的命令上使用 git quote-string,我得到:

"!git filter-branch -f --msg-filter \"sed -e \\\"s/\\[ci skip\\]$//g\\\"\" master..HEAD #"

因此,要使用 OP 的首选别名,请在 [alias] 中的 ~/.gitconfig 下添加:

unwip = "!git filter-branch -f --msg-filter \"sed -e \\\"s/\\[ci skip\\]$//g\\\"\" master..HEAD #"

调试

有时很高兴看到引擎盖下发生了什么。试试这个别名:

debug  = "!set -x; GIT_TRACE=2 GIT_CURL_VERBOSE=2 GIT_TRACE_PERFORMANCE=2 GIT_TRACE_PACK_ACCESS=2 GIT_TRACE_PACKET=2 GIT_TRACE_PACKFILE=2 GIT_TRACE_SETUP=2 GIT_TRACE_SHALLOW=2 git"

只需在 git 之间插入 debug 和通常会出现的任何内容,例如对于 OP 的问题:

git debug unwip


+ git 使用/bin/sh 来执行以!* 开头的别名。要解决此问题,请创建如下命令行:bash -c 'echo \\\"',然后将其传递给 git quote-string

* 参见“调试”标题以获得证明

【讨论】:

太棒了!一个问题是当我运行 git quote-string it outputs on multiple lines 时。您还在帖子中引用了git shell-quote,我想您的意思是quote-string 谢谢。我修复了术语并从我的工作gitconfig 复制/粘贴为quote-string。我还为多行别名添加了一个脚本。如果您仍有多行输出问题,请在聊天中讨论? 您粘贴的新别名似乎与旧别名相同。 I set up a chatroom 但由于某种原因无法邀请您。【参考方案2】:

编辑此解决方案并非在所有情况下都有效。 Here 是适用于所有情况的正确解决方案。

我使用bash 作为命令行,以下别名对我有用:

unwip = "!f()  git filter-branch --msg-filter 'sed -e "s/[ci skip/]$/g"' $1..HEAD ; ; f"

唯一的缺点是您要指定解释器并始终使用sh。就我而言,我依赖于用户的外壳。虽然我认为这在任何主要的 shell 中都不会成为问题,因为我们只是在做一些基本的事情。

【讨论】:

这是一个不正确的例子——sed -e 之后的" 实际上结束第一个引用的字符串。彩色语法高亮显示了这一点。您很幸运 ; 字符在第二个带引号的字符串中,否则 git 会将 ; 视为注释字符并忽略该行的其余部分。请参阅my answer 以获得正确的解决方案。

以上是关于Git 配置别名转义的主要内容,如果未能解决你的问题,请参考以下文章

git alias 配置

Git别名和配置文件

Git 配置别名

.gitconfig文件位置及git配置别名

Git 别名配置

git取别名配置