Проблемы с git format-patch/am (исправление не применяется)

Я пытаюсь применить несколько исправлений к моему репо и получать сообщение patch does not apply, если не указать параметры --ignore-space-change --ignore-whitespace. Некоторые исправления не могут применяться даже с этими ключами, он говорит, что конфликты разрешаются вручную. (но на самом деле ничего не конфликтует, авто слияние должно было решить это)

Я сделал эксперимент: создал патч от фиксации в моем репо, reset master до предыдущего коммита, попытался применить патч из файла. Такое же сообщение об ошибке.

Любые идеи, почему это может случиться?

UPD команды очень просты:

git format-patch -o ../_patches 0f3bf7874c32b22256ae2d9dc00b1afd6464e43c
git reset --hard 0f3bf7874c32b22256ae2d9dc00b1afd6464e43c
git am ../_patches/0001-test2.patch

(этот идентификатор относится к первой фиксации до последнего)

Ответ 1

Ага! Похоже, я нашел причину. Репозиторий использует концы строк CRLF, но format-patch создает файлы исправлений с LF. Когда я создаю репо с нуля с помощью autocrlf = false и делаю тот же эксперимент, у меня такая же проблема. (выглядит как ошибка в Git)
Любой совет, как это исправить?

UPD мое решение состояло в том, чтобы создать новый репозиторий с autocrlf = true и повторно импортировать все изменения из обоих репозиториев в него.

Ответ 2

Вам нужно передать флаг --keep-cr в git am. Это печально, но из-за конкурирующих стандартов (рабочий стол электронной почты и локальный) выбора действительно нет.

Возможно, вам захочется попробовать создать файл .gitattributes. Пытаясь воссоздать вашу проблему, мне удалось заставить работать, когда я указал файл как требующий CRLF. Обратите внимание, что без нормализации файлов сначала он отображал весь файл как измененный. Я обычно использую .gitattributes с этим:

.gitattributes  export-ignore
.gitignore      export-ignore

*.txt           text
*.C             text trailing-space space-before-tab -indent-with-non-tab
*.rst           text trailing-space space-before-tab -indent-with-non-tab
*.clj           text trailing-space space-before-tab -indent-with-non-tab

*.c             text diff=cpp trailing-space space-before-tab -indent-with-non-tab
*.cpp           text diff=cpp trailing-space space-before-tab -indent-with-non-tab
*.h             text diff=cpp trailing-space space-before-tab -indent-with-non-tab
*.hpp           text diff=cpp trailing-space space-before-tab -indent-with-non-tab
*.py            text diff=python trailing-space space-before-tab -indent-with-non-tab
*.tex           text diff=tex
*.java          text diff=java trailing-space space-before-tab -indent-with-non-tab
*.pl            text diff=perl trailing-space space-before-tab -indent-with-non-tab
*.php           text diff=php
*.rb            text diff=ruby trailing-space space-before-tab -indent-with-non-tab

*.vcproj        eol=crlf
*.dsp           eol=crlf
*.dsw           eol=crlf

*.sh            eol=lf

*.jpg           binary
*.png           binary
*.gif           binary
*.tiff          binary

Вы хотите нормализовать свою строку, завершающуюся в соответствии с gitattributes man page. Другой пользователь SO в конечном итоге отключил core.autocrlf, чтобы получить чистые коммиты и исправления.

Попытка воспроизвести вашу ошибку

$ git init repo
Initialized empty Git repository in c:/tmp/git-eol/repo/.git/
$ cd repo
$ git config --local core.autocrlf false
$ vim foo.txt
$ git add foo.txt
$ git commit -m "Add foo."
[master (root-commit) 3903abd] Add foo.
 1 file changed, 3 insertions(+)
 create mode 100644 foo.txt
$ vim foo.txt
$ git st
## master
 M foo.txt
$ git commit -m "Add more foo." -a
[master 03e991a] Add more foo.
 1 file changed, 2 insertions(+)
$ git format-patch HEAD~1
0001-Add-more-foo.patch
$ vim 0001-Add-more-foo.patch

Посмотрев на файл исправления, который был создан, я вижу следующее:

eC9g2xN.png

Как вы можете видеть, каретка возвращает (^M s) в патче. Это с core.autocrlf=false. Продолжая, я вижу:

$ git reset --hard HEAD~1
HEAD is now at 3903abd Add foo.
$ git am 0001-Add-more-foo.patch
Applying: Add more foo.
error: patch failed: foo.txt:1
error: foo.txt: patch does not apply
Patch failed at 0001 Add more foo.
The copy of the patch that failed is found in:
   c:/tmp/git-eol/repo/.git/rebase-apply/patch
When you have resolved this problem, run "git am --resolved".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
$ git am --abort

Таким образом, патч не применяется хорошо из коробки. Использование --keep-cr было таким же ожидаемым, хотя:

$ git am --keep-cr 0001-Add-more-foo.patch
Applying: Add more foo.
$

Хорошо. Поэтому попробуйте это с помощью core.autocrlf=true (в другом репозитории):

# Removed the initial commands...
$ git format-patch HEAD~1
0001-Add-more-foo.patch
$ git reset --hard HEAD~1
HEAD is now at 525b5aa Initial commit.
$ git am 0001-Add-more-foo.patch
Applying: Add more foo.
$ git config --get core.autocrlf
true

Патч в этом случае повсюду имел окончания LF.