Отключить преобразования Git EOL

101

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


  • Начните с двух машин (компьютер Windows = A, компьютер Linux = B)
  • На обеих машинах: git config --global core.autocrlf false
  • На обеих машинах: git config --global core.eol crlf(на всякий случай)

  • Создайте новый репозиторий на A. Из пустой папки:
    • git init --shared(затем отобразите созданный .gitкаталог)
    • Сделайте новый файл .gitignoreв репозитории
    • Создайте новый файл .gitattributesв репозитории с единственной строкой:* -text
    • git add ., затем git commit -m "initial commit"обойти, например, this .
    • git branch master_recv
    • Добавить пульты
  • Создайте новый файл document.txtв репозитории, содержащий CRLF
  • Фиксация:, git add -Aзатемgit commit -m "<something>"
  • Обратите внимание, что A по- document.txtпрежнему содержит CRLF (и удаление его и сброс с помощью --hardвозвращает версию, все еще с CRLF)

  • Подключите весь каталог к ​​компьютеру B
  • Добавить новый файл, new fileсодержащий CRLF
  • Фиксация:, git add -Aзатемgit commit -m "<something>"
  • Обратите внимание, что B document.txtи B все new fileеще содержат CRLF

  • Потяните мастера B к A: git pull <remote> master:master_recv
  • A document.txtизменилось на LF. Добавленный файл new fileтакже содержит LF.

Проблема не возникает, если B - машина Windows.

Imallett
источник
Был core.autocrlf всегда был ложным? Похоже, \nв вашем репозитории уже есть окончания строк? В вашем репозитории нет настроек для изменения в вашем рабочем каталоге. \n\r\n
Эдвард Томсон
Он не всегда был установлен (например, когда репо было создано изначально). Однако в репо уже не должно быть окончаний строк CR. Кроме того, опять же, я не хочу, чтобы произошли какие-либо изменения.
imallett
Я спрашиваю, потому что ваша установка должна сохранять окончания строк как CRLF. Не могли бы вы опубликовать какой-нибудь файл в своем репозитории с его идентификатором объекта только для моего (по общему признанию, вероятно, раздражающего) назидания?
Эдвард Томсон
@EdwardThomson, что ты имеешь в виду? Репо не является общедоступным (поскольку компьютер Linux не является публичным). Я предполагаю, что вам нужен файл с примером. См. Редактировать.
imallett
Да, я согласен с тем, что в этом файле есть окончания строк CRLF. Не могли бы вы прояснить одну вещь: вы упомянули, что «символы новой строки машины Windows меняются на CR!» Наверняка это была опечатка, или вы действительно получаете окончания строки возврата каретки в стиле Mac OS 9?
Эдвард Томсон

Ответы:

75

Внутри вашего проекта должен быть .gitattributesфайл. В большинстве случаев это должно выглядеть, как показано ниже (или на этом снимке экрана ):

# Handle line endings automatically for files detected as text 
# and leave all files detected as binary untouched.
* text=auto

# Never modify line endings of our bash scripts
*.sh -crlf

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.css           text
*.html          text
*.java          text
*.js            text
*.json          text
*.properties    text
*.txt           text
*.xml           text

# These files are binary and should be left untouched
# (binary is macro for -text -diff)
*.class         binary
*.jar           binary
*.gif           binary
*.jpg           binary
*.png           binary

Измените * text=autoна, * text=falseчтобы отключить автоматическую обработку (см. Снимок экрана ).

Как это:

введите описание изображения здесь

Если в вашем проекте нет файла .gitattributes, то окончания строк задаются настройками git. Чтобы изменить настройки git, сделайте следующее:

Перейдите в файл конфигурации в этом каталоге:

1) C: \ ProgramData \ Git \ config

2) Откройте файл конфигурации в Notepad ++ (или в любом другом текстовом редакторе, который вам больше нравится).

3) Измените "autocrlf =" на false.

введите описание изображения здесь

Ген
источник
31
Зачем использовать картинки вместо тегов кода? Очень неудобно
Клинт
31
Потому что я могу добавить на картинку большую красную рамку, чтобы выделить что-то.
Gene
21
Использование * text=falseне сбрасывает текст: оно оставляет текст, установленный на строковое значение false. Это имеет тот же эффект, что и оставление текста без указания (а не с определенным значением). Использование * -textдает ему особую неустановленную настройку. Снятие атрибута text на пути указывает git не предпринимать попытки преобразования конца строки при возврате или оформлении заказа.
JustAMartin 08
Спасибо @Gene за этот ответ. Это сводило меня с ума весь день, и теперь это решило проблему!
LeopardSkinPillBoxHat
7
Сожалею, что не могу сказать спасибо за этот ответ. Мне стоило полдня, чтобы узнать, что кто-то последовал обманчивому совету. Как отметил @JustAMartin, * text=falseне имеет эффекта. Исправьте, пожалуйста, ответ!
Пол Б.
49

Одно простое решение:

  • убедитесь, что для core.autocrlf установлено значение false для всех репозиториев:
    git config --global core.autocrlf false
  • повторно клонируйте репо и убедитесь, что преобразование EOL не выполнено.
  • или, начиная с Git 2.16 (1 квартал 2018 г.) , сохраните текущее репо и выполнитеgit add --renormalize .

Если преобразования выполняются автоматически, это означает , что в репо есть .gitattributes core.eolдиректива .

В Git 2.8+ (март 2016 г.) проверьте, сохраняется ли преобразование eol с помощью:

git ls-files --eol
VonC
источник
3
ПРОСТО НЕ ИСПОЛЬЗУЙТЕ autocrlfСЕГОДНЯ! unsetted autocrlfэквивалентно false. Вы отстали от модных движений в Git
Lazy Badger
1
Как и выше, я пробовал это (хотя и не с глобальным флагом), и это не сработало. версия git есть 1.8.5.2.
imallett
@IanMallett «На данный момент похоже, что на машине Linux все еще есть CRLF»: он будет, пока вы не нормализуете его содержимое или не клонируете его (как вы это делали в Windows)
VonC
Если вы пытаетесь сделать это только для одного репо, просто запустите, git config core.autocrlf falseупомянув об этом, потому что обычно autocrlf должен быть trueдля Windows и inputдля других, но иногда вам нужно что-то особенное для странных крайних случаев. В моем случае я загрузил несколько файлов и хочу записать внесенные мной изменения, чтобы помнить, что я сделал (в отличие от отслеживания изменений кода). Я не знаю, важны ли окончания строк (и хочу, чтобы различия имели смысл по сравнению с «реальным» материалом), поэтому я отключил autocrlf.
Капитан Ман
11

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

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

Imallett
источник
1
Хороший улов, точнее, чем мой ответ. +1
VonC
4

Из раздела gitattributes (5) Страница руководства "Эффекты"

text

Этот атрибут включает и контролирует нормализацию конца строки. Когда текстовый файл нормализуется, его окончания строки преобразуются в LF в репозитории. Чтобы контролировать, какой стиль окончания строки используется в рабочем каталоге, используйте eolатрибут для отдельного файла и core.eol переменную конфигурации для всех текстовых файлов.

Set

Установка текстового атрибута на пути включает нормализацию конца строки и отмечает путь как текстовый файл. Конечное преобразование выполняется без угадывания типа содержимого.

Unset Снятие атрибута text в пути указывает Git не предпринимать попытки преобразования конца строки при возврате или оформлении заказа.

core.autocrlfв новом (1.7.2+) Git не используется, core.eolа правильная установка | отключение текстового атрибута считается более надежным способом

Ленивый барсук
источник
Но в .gitattributesфайле я явно отключил все как текст, верно? Кроме того, я не вижу в нем возможность отключить преобразование (хотя это crlfможет не иметь никакого эффекта)?
imallett
6
Важная вещь, которую часто путают - чтобы отключить textи предотвратить любое преобразование, вы должны установить .gitattributes в, * -text а не в * text=false. falseне является допустимым значением для textатрибута - git не распознает его и вместо этого вернется к настройке autocrlf по умолчанию. Кроме того, после изменения textзначения вы должны сделать резервную копию всех файлов из вашего локального репо, выполнить фиксацию, затем восстановить файлы с правильным концом строк по мере необходимости и зафиксировать их обратно. Тогда ваш конец строк больше не будет изменен git.
JustAMartin