Проблемы с git format-patch/am (патч не применяется)
Я пытаюсь применить несколько исправлений к своему репо и получаю сообщение patch does not apply
если я не укажу params --ignore-space-change --ignore-whitespace
, Некоторые патчи не могут быть применены даже с этими ключами, это говорит о том, что есть конфликты, которые должны быть решены вручную. (но на самом деле ничего не конфликтует, автоматическое слияние должно было решить эту проблему)
Я провел эксперимент: создал патч из коммита в моем репо, сбросил мастер до предыдущего коммита, попытался применить патч из файла. То же сообщение об ошибке.
Есть идеи, почему это может произойти?
UPD команды очень просты:
git format-patch -o ../_patches 0f3bf7874c32b22256ae2d9dc00b1afd6464e43c
git reset --hard 0f3bf7874c32b22256ae2d9dc00b1afd6464e43c
git am ../_patches/0001-test2.patch
(этот идентификатор относится к первому коммиту до последнего)
2 ответа
Ага! Похоже, я нашел причину. В репозитории используются окончания строк CRLF, но format-patch создает файлы патчей с LF. Когда я создаю репозиторий с нуля с autocrlf=false и выполняю тот же эксперимент, у меня возникает та же проблема. (похоже на ошибку в Git)
Любой совет, как это исправить?
UPD Моим решением было создать свежий репозиторий с autocrlf=true и повторно импортировать в него все изменения из обоих репозиториев.
Вам нужно пройти --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
Вы хотите нормализовать окончание строки в соответствии с man-страницей gitattributes. Другой 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
Глядя на файл патча, который был создан, я вижу это:
Как видите, каретка возвращается (^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-окончания везде.