git am / format-patch: управление форматом концов строк - PullRequest
12 голосов
/ 09 июня 2011

Я создал патч из трех коммитов, используя

git format-patch <revision_three_commits_ago>

Это создаст три файла патча, которые я отправил по почте из своей записной книжки, и прочитал почту на моем настольном компьютере (оба являются коробками Windows).1005 * Когда я делаю сейчас

git am --3way --ignore-space-change *.patch

, патчи применяются, но я не получаю те же идентификаторы SHA1 для коммитов.Немного поиска в исправленных файлах я обнаружил, что измененные строки на моем настольном компьютере заканчиваются на LF, тогда как измененные строки на ноутбуке (где я создал исправление) заканчиваются на CR LF.

Итак, моей первой мыслью было позвонить git am без --ignore-space-change, но это дает мне ошибку ( исправление не применяется ).

Как я мограсскажите git format-patch или git am о том, как обрабатывать окончания строк (msysgit 1.7.4)?

Действительно ли мне нужно взять VIM и изменитьформат файла от UNIX до DOS, прежде чем я смогу применить исправления?


РЕДАКТИРОВАТЬ: Даже изменение файлов исправлений с помощью VIM помогает: я думал, set ff=dosи :%s/^M//g поможет, но это не так!

По моему мнению, применение патча должно дать точно того же контента, а также тот же хеш коммита, который я извлек из другого репо, где был создан патч.Я не думаю об этом?

Ответы [ 4 ]

19 голосов
/ 13 июля 2011

После игры с различными опциями (core.autocrlf, core.eol) я обнаружил, что используя

git am --keep-cr

добивается цели (но вызывает предупреждение о замыкающих пробелах).

Нет необходимости ручного редактирования файла патча или другой грязи.

Но, (конечно) хеш отличается, как описано в ответе nikai ... Спасибо nikai за то, что он указал мне на хэш.

В моем сценарии «ноутбук-рабочий стол» я хотел перенести некоторые изменения в автономном режиме с ноутбука на настольный компьютер, но репозитории не должны расходиться и не должно повторяться одно и то же принятие дважды, когда я применил патч на рабочем столе, а затем сделал git pull desktop из тетради.

Для этого я сделал следующее:

  1. На рабочем столе примените патч, как описано выше, используя git am --keep-cr ...
  2. На ноутбуке, до git pull desktop, что приводит к ситуации, когда каждый коммит, введенный патчем, происходит дважды (один раз для оригинального коммита ноутбука, один раз для пропатченного и извлеченного коммита на рабочем столе)
  3. Теперь (находясь в ветке master ноутбука), выдача git rebase desktop/master приводит к сообщению No changes -- Patch already applied и выводит исходные коммиты с ноутбука, замененные коммитами с рабочего стола
5 голосов
/ 01 февраля 2015

Git 2.3.0 (февраль 2015 г.) предложит еще одну новую опцию: --transfer-encoding, чтобы указать используемую кодировку передачи (quoted-printable, 8bit, base64) вместо того, чтобы полагаться только на--keep-cr.

git send-email справочная страница .
git am справочная страница .

См. коммит 8d81408 от Паоло Бонзини (bonzini) :

git-send-email: добавить --transfer-encoding опция

список рассылки детализирует проблемы при применении исправлений с "git am" в репозитории с окончаниями строк CRLF.
В примере в потоке, репозиторий возник из "git-svn", поэтому это не такможно использовать core.eol и друзей на нем.

Прямо сейчас, лучший вариант - использовать "git am --keep-cr".
Однако, когда патч создает новые файлы, процесс приложения патча будет отклоненновый файл, потому что он находит строку "/dev/null\r" вместо "/dev/null".

Проблема в том, что SMTP-транспорт является CRLF-небезопасным .
SeПоиск патча по электронной почте аналогичен прохождению его через «dos2unix | unix2dos».
Вновь введенные CRLF обычно прозрачны, потому что git-am удаляет их.Параметр keepcr=true сохраняет их, но в основном он работает случайно, и было бы очень проблематично иметь рабочий процесс "git am" в репозитории со смешанными окончаниями строк LF и CRLF.

MIME-решение для этого - передача в кавычках для печати, включающая .
Это не то, что мы хотим включить по умолчанию, так как это делает ужасным просмотр полученных писем.
Тем не менее, это очень хорошее соответствие для проектов, которые хранят окончания строк CRLF в репозитории.

Единственный недостаток quoted-printable заключается в том, что исправления в кавычках не применяются, если сопровождающийиспользует "git am --keep-cr".
Это связано с тем, что декодированный патч будет иметь два возврата каретки в конце строки.
Поэтому добавьте поддержку base64, а также кодировку передачи , которая делает полученнымэлектронные письма просто невозможно просмотреть за пределами MUA (Mail User Agent) , но на самом деле просто работает.

Патч охватывает все базы, включая Users, которые все еще живут в конце 80-х, также предоставляя 7-битную кодировку передачи контента, которая отказывается отправлять электронные письма с не-ASCII символом в них.
И, наконец, «8bit» добавит заголовок Content-Transfer-Encoding, но в противном случаеничего не делать.

Документ для git send-email теперь будет содержать:

--transfer-encoding=(7bit|8bit|quoted-printable|base64)

Укажите кодировку передачи, которая будет использоваться для отправки сообщения по SMTP.
7bit потерпит неудачу при обнаружении сообщения не-ASCII.

Quoted-printable может быть полезен, когда репозиторий содержит файлы, содержащие возврат каретки, но делает необработанный файл электронной почты патча (как сохраненный из MUA) намного труднее проверять вручную.
base64 еще более глупыйдоказательство, но также еще более непрозрачный.

По умолчанию используется значение конфигурации 'sendemail.transferEncoding';если это не указано, git будет использовать 8 бит и не будет добавлять заголовок Content-Transfer-Encoding.

3 голосов
/ 04 июля 2011

Здесь был похожий вопрос: очевидно, что те же самые коммиты дают разный sha1, почему?

В качестве краткого резюме, git cat-file commit <sha> должен быть в состоянии сузить дерево, родители,адреса электронной почты, даты, имена от автора или коммиттера различаются, или если в сообщениях о коммите был добавлен дополнительный '\ n'.

2 голосов
/ 28 июня 2012

Краткий ответ: git am --committer-date-is-author-date

Длинная история: я только что обнаружил, что был в одной лодке, когда пытался ситакернет коммитов между двумя репозиториями.Поэкспериментировав с параметрами git am, я заметил, что идентификаторы файлов всегда совпадали, но при последовательных прогонах git am были получены разные идентификаторы фиксации для одних и тех же параметров.Оказывается, есть две метки времени - метка времени автора, которую вы обычно видите, и метка времени коммиттера, когда создается коммит.Последний по умолчанию установлен на текущее время в git am.Вам нужен параметр --committer-date-is-author-date, чтобы синхронизировать даты, что, в свою очередь, синхронизирует ваши идентификаторы фиксации.

Из-за этого я бы сказал, что git bundle гораздо надежнее, если этовариант в вашей среде.

...