Git配置别名转义

时间:2016-06-27 14:59:24

标签: git bash escaping git-alias

我正在尝试编写一个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它抱怨配置错误,但我希望它的行为与以前的逗号一样。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:10)

通用解决方案

获取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]的{​​{1}}下添加:

~/.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,例如OP的问题:

git

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

git quote-string请参阅“调试”标题以获取证明

答案 1 :(得分:2)

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

我正在使用public function socialProvider(){ return $this->hasOne('App/SocialProvider'); } 作为命令行,以下别名对我有用:

bash

唯一的缺点是你指定了解释器并始终使用unwip = "!f() { git filter-branch --msg-filter 'sed -e "s/[ci skip/]$/g"' $1..HEAD ; }; f" 。在我的情况下,我依赖于用户的shell。虽然我不相信它会成为任何主要炮弹中的问题,因为我们只做基本的东西。