9

我正在尝试编写一个 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它抱怨配置错误,但我希望它表现得像以前的逗号。我怎样才能解决这个问题?

4

2 回答 2

22

通用解决方案

让一个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的具体问题

使用git quote-stringOP 的命令,我得到:

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

因此,要使用 OP 的首选别名,请在[alias]in下~/.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"

只需插入debug通常git会遵循的内容,例如对于 OP 的问题:

git debug unwip


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

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

于 2016-09-21T12:30:16.350 回答
3

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

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

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

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

于 2016-06-28T08:56:04.513 回答