Как преобразования конца строки работают с git core.autocrlf между различными операционными системами

220

Я прочитал много разных вопросов и ответов по переполнению стека, а также git документацию о том, как работает параметр core.autocrlf .

Это мое понимание того, что я прочитал:

Клиенты Unix и Mac OSX (pre-OSX использует CR) используют LF-окончания строк.
Клиенты Windows используют окончания строки CRLF.

Когда для core.autocrlf на клиенте установлено значение true, репозиторий git всегда сохраняет файлы в формате окончания строки LF, а окончания строк в файлах на клиенте конвертируются туда-обратно при извлечении / фиксации для клиентов (т. Е. Windows), которые используют не -LF окончания строк, независимо от формата файлов окончаний строк на клиенте (это не согласуется с определением Тима Клема - см. Обновление ниже).

Вот матрица, которая пытается документировать то же самое для параметров «input» и «false» в файле core.autocrlf с вопросительными знаками, где я не уверен в поведении преобразования конца строки.

Мои вопросы:

  1. Какими должны быть знаки вопроса?
  2. Правильна ли эта матрица для «не вопросительных знаков»?

Я обновлю вопросительные знаки из ответов, поскольку консенсус, кажется, сформирован.

                       значение core.autocrlf
            верный ввод ложный
-------------------------------------------------- --------
совершать | перерабатывать ? ?
новый | в LF (преобразовать в LF?) (без преобразования?)

совершать | Перевести в ? нет
существующий | LF (конвертировать в LF?) Конвертация

оформить заказ | Перевести в ? нет
существующий | CRLF (без конвертации?) Конвертация

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

-

Обновление 17.04.2012 : После прочтения статьи Тима Клема, связанной JJD в комментариях, я изменил некоторые значения в «неизвестных» значениях в приведенной выше таблице, а также изменил «checkout существующие | true для преобразования». в CRLF вместо конвертации в клиента ". Вот определения, которые он дает, которые более понятны, чем все, что я видел в других местах:

core.autocrlf = false

Это значение по умолчанию, но большинству людей рекомендуется изменить это немедленно. Результатом использования false является то, что Git никогда не связывается с окончаниями строк в вашем файле. Вы можете проверить файлы с помощью LF, CRLF или CR, или какой-то случайной комбинации этих трех, и Git это не волнует. Это может затруднить чтение различий и затруднить их объединение. Большинство людей, работающих в мире Unix / Linux, используют это значение, потому что у них нет проблем с CRLF, и им не нужно, чтобы Git выполнял дополнительную работу всякий раз, когда файлы записываются в базу данных объектов или записываются в рабочий каталог.

core.autocrlf = true

Это означает, что Git обработает все текстовые файлы и удостоверится, что CRLF заменяется на LF при записи этого файла в базу данных объектов и превратит все LF обратно в CRLF при записи в рабочий каталог. Это рекомендуемый параметр в Windows, поскольку он гарантирует, что ваш репозиторий можно использовать на других платформах, сохраняя CRLF в вашем рабочем каталоге.

core.autocrlf = вход

Это означает, что Git обработает все текстовые файлы и убедится, что CRLF заменяется на LF при записи этого файла в объектную базу данных. Это не будет, однако, делать обратное. Когда вы читаете файлы обратно из базы данных объектов и записываете их в рабочий каталог, они все равно будут иметь LF для обозначения конца строки. Этот параметр обычно используется в Unix / Linux / OS X для предотвращения записи CRLF в репозиторий. Идея заключалась в том, что если вы вставили код из веб-браузера и случайно поместили CRLF в один из ваших файлов, Git удостоверится, что они будут заменены на LF при записи в базу данных объектов.

Статья Тима отличная, единственное, о чем я могу подумать, что она отсутствует, это то, что он предполагает, что репозиторий имеет формат LF, что не всегда верно, особенно для проектов только для Windows.

Сравнение статьи Тима с ответом jmlane, получившим наибольшее количество голосов на сегодняшний день, показывает идеальное согласие с истинными и исходными настройками и несогласие с ложными настройками.

Майкл Мэддокс
источник
7
Сохранить autocrlfложь кажется намного проще;) stackoverflow.com/questions/2333424/…
VonC
@VonC: я читал это, и я думаю, что понимаю это, но я не обязательно могу сделать выбор. Я работаю с репозиториями git, которые не контролирую, которые требуют, чтобы я установил значение определенным образом.
Майкл Мэддокс
5
Не было бы неплохо, если бы Windows тоже нормализовалась до LF? Mac имел обыкновение быть CR (ранее v10), но теперь нормализовано к LF.
Бретт Райан
3
Мне нужно добавить ссылку на замечательную статью Тимофея Клема - пожалуйста, прочитайте « Разум, конец вашей линии» .
JJD
1
Сценарий: я разработчик Linux / Windows. Я использую только текстовые редакторы, которые могут распознавать оба типа концов строк (IE. Vim, eclipse). Мне нужно только (хочу) работать с файлами, оканчивающимися на LF. В настоящее время у меня установлен core.autocrlf = input в моей глобальной конфигурации git. Мне хорошо идти? Будет ли у меня когда-нибудь конфликт?
Крис

Ответы:

129

Лучшее объяснение того, как это core.autocrlfработает, можно найти на справочной странице gitattributes в разделе textатрибутов.

Вот как core.autocrlfработает в настоящее время (или, по крайней мере, начиная с v1.7.2, насколько я знаю):

  • core.autocrlf = true
    1. Текстовые файлы, извлеченные из хранилища, содержащие только LFсимволы, нормализуются CRLFв вашем рабочем дереве; файлы, которые содержатся CRLFв хранилище, не будут затронуты
    2. Текстовые файлы, содержащие только LFсимволы в репозитории, нормализуются от CRLFдо, LFкогда фиксируются обратно в репозиторий. Файлы, содержащиеся CRLFв хранилище, будут сохранены без изменений.
  • core.autocrlf = input
    1. Текстовые файлы, извлеченные из хранилища, сохранят оригинальные символы EOL в вашем рабочем дереве.
    2. Текстовые файлы в вашем рабочем дереве с CRLFсимволами нормализуются, LFкогда они возвращаются в хранилище.
  • core.autocrlf = false
    1. core.eol диктует символы EOL в текстовых файлах вашего рабочего дерева.
    2. core.eol = nativeпо умолчанию это означает, что Windows EOL есть, CRLFа * nix EOLLF в рабочих деревьях.
    3. gitattributesНастройки репозитория определяют нормализацию символов EOL для коммитов в репозиторий (по умолчанию нормализация для LFсимволов).

Я только недавно исследовал эту проблему, и я также считаю, что ситуация очень запутанная. core.eolУстановка определенно помогла уточнить , как символы EOL обрабатывается мерзавцем.

jmlane
источник
3
для autocrlf = true не должно быть следующего? Текстовые файлы, содержащие только символы CRLF EOL в хранилище, нормализуются из CRLF в LF при фиксации обратно в хранилище. Файлы, содержащие LF в хранилище, будут сохранены без изменений.
Петр Левандовски
2
Для меня, даже если autocrlf = false, git конвертирует EOL в CRLF. Прочитав этот ответ, я понял, что мой файл .gitattribute имеет text = auto set, что вызывает проблему.
irsis
1
Ведь core.autocrlf = falseесли у меня нет gitattributesфайла, значит ли это, что нормализации не будет? Или это означает, что будет использоваться нормализация по умолчанию?
Чин
Разве .gitattributesфайл не должен иметь приоритет над core.autocrlfнастройкой?
Qwerty
63

Проблема EOL в проектах на смешанных платформах давно делает мою жизнь несчастной. Проблемы обычно возникают , когда уже есть файлы с различным и смешанным EOL в уже в репо. Это означает, что:

  1. В репо могут быть разные файлы с разными EOL
  2. Некоторые файлы в репо могут иметь смешанную EOL, например, комбинацию CRLFи LFв одном и том же файле.

Как это происходит, здесь не проблема, но это случается.

Я провел несколько тестов конвертации в Windows для различных режимов и их комбинаций.
Вот что я получил в слегка измененной таблице:

                 | Результирующее преобразование, когда | Результирующее преобразование, когда
                 | фиксация файлов с различными | проверка из репо -
                 | EOLS INTO РЕПО и | со смешанными файлами в нем и
                 | Значение core.autocrlf: | Значение core.autocrlf:           
-------------------------------------------------- ------------------------------
Файл | правда | вход | ложь | правда | вход | ложный
-------------------------------------------------- ------------------------------
Windows-CRLF | CRLF -> LF | CRLF -> LF | как есть | как есть | как есть | как есть
Unix -LF | как есть | как есть | как есть | LF -> CRLF | как есть | как есть
Mac -CR | как есть | как есть | как есть | как есть | как есть | как есть
Смешанный-CRLF + LF | как есть | как есть | как есть | как есть | как есть | как есть
Смешанный-CRLF + LF + CR | как есть | как есть | как есть | как есть | как есть | как есть

Как вы можете видеть, есть 2 случая, когда преобразование происходит при фиксации (3 левых столбца). В остальных случаях файлы сохраняются как есть.

При оформлении заказа (3 правых столбца) конверсия происходит только в одном случае, когда:

  1. core.autocrlfэто true и
  2. файл в репо имеет LFEOL.

Самое удивительное для меня, и я подозреваю, что причина многих проблем с EOL заключается в том, что нет конфигурации, в которой смешанный EOL, такой как CRLF+, LFнормализуется.

Также обратите внимание, что «старые» Mac только из EOL CRникогда не конвертируются.
Это означает, что если плохо написанный сценарий преобразования EOL пытается преобразовать смешанный конечный файл с помощью CRLFs + LFs, просто преобразовав LFs в CRLFs, то он оставит файл в смешанном режиме с «одинокими», CRкуда бы он ни CRLFбыл преобразован CRCRLF.
Git не будет ничего конвертировать, даже в trueрежиме, и EOL хаос продолжается. Это на самом деле произошло со мной и испортило мои файлы очень сильно, поскольку некоторые редакторы и компиляторы (например, VS2010) не любят Mac EOL.

Я предполагаю, что единственный способ действительно решить эти проблемы - это иногда нормализовать весь репозиторий, проверяя все файлы в режиме inputили falseрежиме, выполняя надлежащую нормализацию и повторно фиксируя измененные файлы (если таковые имеются). На Windows, предположительно, возобновить работу с core.autocrlf true.

Ади Шавит
источник
4
Отличный ответ, но одно предложение, с которым я не могу согласиться, - « На Windows», по-видимому, возобновить работу сcore.autocrlf true . Я лично считаю, что inputследует использовать всегда.
Г. Демецки
39

Ситуация "Eol Conversion" скоро изменится с выходом Git 1.7.2 :

Новый параметр конфигурации core.eolдобавляется / развивается :

Это замена core.eolкоммита 'Add " " config variable ", который в данный момент находится pu(последний в моей серии).
Вместо того, чтобы подразумевать, что " core.autocrlf=true" является заменой для " * text=auto", он явно указывает на тот факт, что он autocrlfпредназначен только для пользователей, которые хотят работать с CRLF в своем рабочем каталоге в хранилище, которое не имеет нормализации текстовых файлов .
Когда он включен, «core.eol» игнорируется.

Введите новую переменную конфигурации " core.eol", которая позволяет пользователю указать, какие окончания строк использовать для нормализованных в конце строк файлов в рабочем каталоге.
По умолчанию это " native", что означает CRLF в Windows и LF везде. Обратите внимание, что " core.autocrlf" переопределяет core.eol.
Это означает, что:

[core]
  autocrlf = true

помещает CRLF в рабочий каталог, даже если для core.eolнего установлено значение " lf".

core.eol:

Устанавливает тип окончания строки для использования в рабочем каталоге для файлов с установленным textсвойством.
Альтернативами являются 'lf', 'crlf' и 'native', которые используют окончание собственной строки платформы.
Значением по умолчанию является native.


Другие эволюции рассматриваются :

Для 1.8, я бы рассмотреть возможность core.autocrlfпросто включить нормализацию и оставить рабочий каталог конца строки решения для core.eol, но это будет нарушать установки людей.


git 2.8 (март 2016 г.) улучшает способ core.autocrlfвлияния на eol:

См. Коммит 817a0c7 (23 февраля 2016 года), коммит 6e336a5 , коммит df747b8 , коммит df747b8 (10 фев 2016), коммит df747b8 , совершают df747b8 (10 Feb 2016), а также совершать 4b4024f , совершают bb211b4 , совершают 92cce13 , совершают 320d39c , совершают 4b4024f , коммит bb211b4 , коммит 92cce13 , коммит 320d39c (05 февраля 2016 г.) от Torsten Bögershausen ( tboegi) .
(Слиты Junio C Hamano - gitster- в коммите c6b94eb, 26 Feb 2016)

convert.c: рефакторинг crlf_action

Рефакторинг определения и использования crlf_action.
Сегодня, когда crlfдля файла crlf_actionне установлен атрибут " ", устанавливается значение CRLF_GUESS. Используйте CRLF_UNDEFINEDвместо этого и ищите " text" или " eol" как прежде.

Заменить старое CRLF_GUESSиспользование:

CRLF_GUESS && core.autocrlf=true -> CRLF_AUTO_CRLF
CRLF_GUESS && core.autocrlf=false -> CRLF_BINARY
CRLF_GUESS && core.autocrlf=input -> CRLF_AUTO_INPUT

Проясните, что к чему, определив:

- CRLF_UNDEFINED : No attributes set. Temparally used, until core.autocrlf
                   and core.eol is evaluated and one of CRLF_BINARY,
                   CRLF_AUTO_INPUT or CRLF_AUTO_CRLF is selected
- CRLF_BINARY    : No processing of line endings.
- CRLF_TEXT      : attribute "text" is set, line endings are processed.
- CRLF_TEXT_INPUT: attribute "input" or "eol=lf" is set. This implies text.
- CRLF_TEXT_CRLF : attribute "eol=crlf" is set. This implies text.
- CRLF_AUTO      : attribute "auto" is set.
- CRLF_AUTO_INPUT: core.autocrlf=input (no attributes)
- CRLF_AUTO_CRLF : core.autocrlf=true  (no attributes)

Как Торек добавляет в комментариях :

все эти переводы (любое преобразование EOL из eol=или autocrlfнастроек и « cleanфильтры») выполняются, когда файлы перемещаются из рабочего дерева в индекс , т. е. во время, git addа не во git commitвремя.
(Обратите внимание, что git commit -aили --onlyили --includeдобавьте файлы в индекс в то время.)

Подробнее об этом см. «В чем разница между autocrlf и eol ».

VonC
источник
18
Это, к сожалению, не добавляет ясности для меня. Похоже, они говорят, что есть проблемы с текущей реализацией (неясно, что это за проблемы), и они увеличивают сложность в попытке решить эти неуказанные проблемы. На мой взгляд, настройка core.autocrlf уже слишком сложна и недостаточно документирована, и эта ситуация, похоже, ухудшается. Еще раз спасибо за головы.
Майкл Мэддокс
1
Это не кажется удовлетворительным решением и, похоже, имеет те же проблемы, что и core.autocrlf. Я предпочел бы, чтобы git никогда ничего не изменял автоматически, но предупреждал бы пользователя, который хочет добавить или зафиксировать неправильные окончания строк. Таким образом, вам понадобится опция командной строки, чтобы git add мог добавить «неправильные» окончания строки. (вероятно, git add - лучшее место, чтобы проверить это, чем git commit)
donquixote
Это заставит соответствующего пользователя изменить настройки редактора и действительно позаботиться о проблеме. Хотя это позволило бы оставлять «неправильные» окончания строк для файлов от сторонних производителей или уже проверенных в репозитории.
Donquixote
@donquixote еще раз, я согласен. Но core.eolречь идет об «автоматическом изменении» только того, что вы явно объявили в .gitattributesфайле. Это отличается от того, core.autocrlfкоторый применяется к любому файлу в репо. Это декларативный процесс.
VonC
1
@donquixote: Я понимаю, что это довольно старый, но я только сейчас читаю ваш комментарий. Фактически все эти переводы (любое преобразование EOL из настроек eol = или autocrlf и «чистые» фильтры) выполняются, когда файлы перемещаются из рабочего дерева в индекс, т. Е. Во время, git addа не во git commitвремя. (Обратите внимание , что git commit -aили --onlyили --includeделать добавление файлов в индекс в то время, хотя.) Для чего это стоит, вы и я , и Линус Торвальдс все ненавидите идею о VCS когда - либо изменений , что совершается. Но все эти пользователи Windows , ... :-)
Торек
34

core.autocrlfзначение не зависит от типа ОС, но для Windows значение по умолчанию - trueи для Linux - input. Я исследовал 3 возможных значения для случаев фиксации и извлечения, и вот таблица:

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ core.autocrlf ║     false    ║     input    ║     true     ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => LF   ║
║ git commit    ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => LF   ║ CRLF => LF   ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => CRLF ║
║ git checkout  ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝
прэтт
источник
5
Короткое резюме в словах: Файлы с CRодним никогда не трогаются. falseникогда не касается концов строк. trueвсегда совершает как LFи проверяет как CRLF. И inputвсегда фиксирует как LFи проверяет как есть.
Фуркан Камбай
7

Вот мое понимание этого до сих пор, на случай, если это кому-то поможет.

core.autocrlf=true и core.safecrlf = true

У вас есть репозиторий, в котором все окончания строк одинаковы , но вы работаете на разных платформах. Git позаботится о том, чтобы окончания строк были преобразованы в значения по умолчанию для вашей платформы. Почему это важно? Допустим, вы создаете новый файл. Текстовый редактор на вашей платформе будет использовать окончания строк по умолчанию. Когда вы включаете его, если у вас не установлено значение true для core.autocrlf, вы вводите несоответствие конца строки для кого-то на платформе, которая по умолчанию имеет другое окончание строки. Я тоже всегда устанавливаю safecrlf, потому что хотел бы знать, что операция crlf обратима. С этими двумя настройками git изменяет ваши файлы, но проверяет, что изменения обратимы .

core.autocrlf=false

У вас есть репозиторий, в котором уже зарегистрированы смешанные окончания строк, и исправление неправильных окончаний строк может привести к поломке. В этом случае лучше не указывать git преобразовывать окончания строк, потому что тогда это усугубит проблему, для решения которой оно было разработано - облегчить чтение различий и объединить менее болезненные. С этим параметром git не изменяет ваши файлы .

core.autocrlf=input

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

деревенщина
источник
3

Нет, ответ @jmlane неправильный.

Для Checkin (git add, git commit):

  1. если textсвойство имеет значение Set, Set value to 'auto', преобразование происходит, если файл был зафиксирован с помощью CRLF.
  2. если textсвойство Unset: ничего не происходит, enen дляCheckout
  3. если textсвойство есть Unspecified, конвертация зависит отcore.autocrlf
    1. Если autocrlf = input or autocrlf = trueпреобразование происходит только тогда, когда файл в хранилище имеет значение «LF», если это был «CRLF», ничего не произойдет.
    2. если autocrlf = falseничего не происходит

Для Checkout:

  1. если textсвойство есть Unset: ничего не происходит.
  2. если textсвойство Set, Set value to 'auto: это зависит от того core.autocrlf, core.eol.
    1. core.autocrlf = input: ничего не происходит
    2. core.autocrlf = true: преобразование происходит только тогда, когда файл в хранилище имеет значение «LF», «LF» -> «CRLF»
    3. core.autocrlf = false: преобразование происходит только тогда, когда файл в хранилище имеет значение «LF», «LF» -> core.eol
  3. если textсвойство Unspecified, это зависит от core.autocrlf.
    1. такой же как 2.1
    2. такой же как 2.2
    3. Ничего, ничего не происходит, core.eol не эффективен, когда textсвойствоUnspecified

Поведение по умолчанию

Таким образом, поведение по умолчанию является textсвойством Unspecifiedи core.autocrlf = false:

  1. для регистрации ничего не происходит
  2. для оформления заказа ничего не происходит

Выводы

  1. если textсвойство установлено, поведение при регистрации зависит от самого себя, а не от autocrlf
  2. autocrlf или core.eol для поведения извлечения, и autocrlf> core.eol
ViciOs
источник
2

Провел несколько тестов как на Linux, так и на Windows. Я использую тестовый файл, содержащий строки, оканчивающиеся на LF, а также строки, оканчивающиеся на CRLF.
Файл зафиксирован, удален и затем извлечен. Значение core.autocrlf устанавливается перед фиксацией, а также перед извлечением. Результат ниже.

commit core.autocrlf false, remove, checkout core.autocrlf false: LF=>LF   CRLF=>CRLF  
commit core.autocrlf false, remove, checkout core.autocrlf input: LF=>LF   CRLF=>CRLF  
commit core.autocrlf false, remove, checkout core.autocrlf true : LF=>LF   CRLF=>CRLF  
commit core.autocrlf input, remove, checkout core.autocrlf false: LF=>LF   CRLF=>LF  
commit core.autocrlf input, remove, checkout core.autocrlf input: LF=>LF   CRLF=>LF  
commit core.autocrlf input, remove, checkout core.autocrlf true : LF=>CRLF CRLF=>CRLF  
commit core.autocrlf true, remove, checkout core.autocrlf false: LF=>LF   CRLF=>LF  
commit core.autocrlf true, remove, checkout core.autocrlf input: LF=>LF   CRLF=>LF  
commit core.autocrlf true,  remove, checkout core.autocrlf true : LF=>CRLF CRLF=>CRLF  
Люк Депоортер
источник