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' | ';' | '#')*

Кроме того:

  1. Комментарий начинается с;или#за пределами цитируемого раздела и распространяется до конца строки.
  2. Следующая обратная косая черта позволяет избежать работы:\t,\n,\b,\",\\. Они работают одинаково в цитируемых и нецитируемых разделах. Другие escape-последовательности вызывают ошибку.
  3. Вы также можете игнорировать новую строку, поставив\в конце строки. Опять же, это работает одинаково в цитируемых и нецитируемых разделах.

Вот пример:

      # !echo some ";"
    foo="!echo "some "\";\""

Конечно, после всего этого я обнаружил, что это не работает, потому что мой ключ содержал_. Какой мерзавец.

Другие вопросы по тегам