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
помогут, но это не так!
По моему мнению, применение патча должно привести к тому, что точно тот же контент, а также тот же самый хеш-хэт, как я вытащил из другого репо, где был создан патч. Я думаю об этом неправильно?
Ответы
Ответ 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
намного надежнее, если это вариант в вашей среде.