Подтвердить что ты не робот

Git am/format-patch: формат управления концами строк

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

git format-patch <revision_three_commits_ago>

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

Когда я делаю сейчас

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 помогут, но это не так!

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

4b9b3361

Ответ 1

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

git am --keep-cr

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

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

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

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

Чтобы достичь этого, я сделал следующее:

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

Ответ 2

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

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

См. commit 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-небезопасным.
Отправка патча по электронной почте такая же, как передача его через "dos2unix | unix2dos".
Недавно введенные CRLF обычно прозрачны, потому что git-am разделяет их. Параметр keepcr=true сохраняет их, но в основном работает случайно, и было бы очень проблематично иметь рабочий процесс "git am" в репозитории со смешанными концами строк LF и CRLF.

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

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

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

В doc для git send-email будет теперь включаться:

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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