Git config псевдоним Escape
Я пытаюсь написать псевдоним 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
он жалуется на плохой конфиг, но я ожидаю, что он будет вести себя как предыдущие комманд. Как я могу это исправить?
3 ответа
РЕДАКТИРОВАТЬ Это решение не работает во всех случаях. Вот правильное решение, которое работает во всех случаях.
я использую bash
как командная строка и следующий псевдоним работал для меня:
unwip = "!f() { git filter-branch --msg-filter 'sed -e "s/[ci skip/]$/g"' $1..HEAD ; }; f"
Единственным недостатком является то, что вы указываете переводчика и всегда используете sh
, В моем случае я полагаюсь на оболочку пользователя. Хотя я не верю, что это будет проблемой в любой из основных оболочек, поскольку мы занимаемся только базовыми вещами.
Универсальное решение
Получение 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 '\\\"' #"
Чтобы процитировать многострочную строку, я написал более длинный скрипт, который я предлагаю вам запустить как:
git quote-string |
sponge
Отвечая на конкретный вопрос ОП
С помощью 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"
Просто вставьте debug
между git
и то, что обычно следует, например, для вопроса ОП:
git debug unwip
+
git
использования /bin/sh
выполнять псевдонимы, начиная с !
* Чтобы обойти это, создайте командную строку как: bash -c 'echo \\\"'
а затем передать это git quote-string
,
*
Смотрите заголовок "Отладка" для доказательства
git
очень полезно и просто сообщает об этой ошибке при любой проблеме :
fatal: bad config line 19 in file /home/you/.gitconfig
Получайте удовольствие, пробуя миллионы комбинаций кавычек и переходов, чтобы понять это!
В конце концов я прибег к чтению исходного кода . Вот как он анализирует псевдоним:
alias = isspace* iskeychar+ spacetab* '=' value
isspace = ' ' | '\t' | '\v' | '\f' | '\r' (but not '\n')
spacetab = ' ' | '\t'
iskeychar = 'a'-'Z' | 'A'-'Z' | '0'-'9' | '-'
value = (quoted | unquoted)*
quoted = '"' not('\n')* '"'
unquoted = not('\n' | ';' | '#')*
Кроме того:
- Комментарий начинается с
;
или#
за пределами цитируемого раздела и распространяется до конца строки. - Следующая обратная косая черта позволяет избежать работы:
\t
,\n
,\b
,\"
,\\
. Они работают одинаково в цитируемых и нецитируемых разделах. Другие escape-последовательности вызывают ошибку. - Вы также можете игнорировать новую строку, поставив
\
в конце строки. Опять же, это работает одинаково в цитируемых и нецитируемых разделах.
Вот пример:
# !echo some ";"
foo="!echo "some "\";\""
Конечно, после всего этого я обнаружил, что это не работает, потому что мой ключ содержал_
. Какой мерзавец.