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

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

8 ответов

Лучшее объяснение того, как 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 EOLs CRLF и *nix EOLs LF в рабочих деревьях.
    3. вместилище gitattributes Настройки определяют нормализацию символов EOL для коммитов в репозиторий (по умолчанию нормализация LF персонажи).

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

Проблема 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. файл в репо имеет LF EOL.

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

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

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

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

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ core.autocrlf ║     false    ║     input    ║     true     ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║ git commit    ║ LF => LF     ║ LF => LF     ║ LF => LF     ║
║               ║ CR => CR     ║ CR => CR     ║ CR => CR     ║
║               ║ CRLF => CRLF ║ CRLF => LF   ║ CRLF => LF   ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║ git checkout  ║ LF => LF     ║ LF => LF     ║ LF => CRLF   ║
║               ║ CR => CR     ║ CR => CR     ║ CR => CR     ║
║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝

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

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

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

Введите новую переменную конфигурации " core.eol msgstr ", который позволяет пользователю указать, какие окончания строки использовать для нормализованных в конце строки файлов в рабочем каталоге.
По умолчанию " 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 фев 2016 г.) и коммит 4b4024f, коммит bb211b4, коммит 92cce13, коммит 320d39c, коммит 4b40 коммит bb211b4, коммит 92cce13, коммит 320d39c (05 февраля 2016 г.) от Torsten Bögershausen ( tboegi )
(Объединено Юнио С Хамано - gitster - в коммите c6b94eb, 26 февраля 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)

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

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

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

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

core.autocrlf=true а также core.safecrlf = true

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

core.autocrlf=false

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

core.autocrlf=input

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

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

За Checkin (git add, git commit):

  1. если text свойство Set, Set value to 'auto', преобразование происходит, если файл был зафиксирован с помощью CRLF
  2. если text свойство Unset: ничего не происходит 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

Провел несколько тестов как на 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  

Заявление core.autocrlf=true ведущий к CRLF -> LFна фиксации все неправильно! Не все так просто, как вы увидите ...

В документах говорится, что этот параметр соответствует ... «in and be set to in git config» ... что именно означает?

Это означает, что если для файла не установлен текстовый атрибут, а если есть, то теперь это зависит от того, является ли фиксируемый файл новым (в этом случае да, он будет нормализован до LF в базе данных репозитория git), или был ли это уже существующий файл, который вы редактировали и сейчас фиксируете (в этом случае НИЧЕГО не произойдет ... если вы не запустите git add --renormalize . в этом случае он будет нормализован в базе данных репозитория git).

Видите ли ... весь механизм происходит только с файлом, для которого a не поместил вариант текстового атрибута: text, -text,.

Итак, на что вам действительно стоит обратить внимание, так это на использование .gitattributes с настройкой по умолчанию для всех ваших файлов:

      * -text
# followed by specialization

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

      *  text=auto
# followed by specialization

Это означает, что все файлы (кроме специализаций), которые git автоматически определяет как небинарные (текстовые) и которые есть в базе данных git [см. примечание 1.], будут получать каждый раз:
    • core.autocrlf является true, или
    • является crlf, или
    • core.eol является native(по умолчанию), и вы используете платформу Windows.
Во всех остальных случаях вы получите.

Какие специализации я имею в виду? Например, имея .bat файлы быть CRLF а также .sh файлы быть LF либо через:

      *.sh           text eol=lf

# *.bat
*.[bB][aA][tT] text eol=crlf

или

      # *.sh are committed correctly as-is (LF)
*.sh           -text

# *.bat are committed correctly as-is (CRLF)
*.[bB][aA][tT] -text

Так что да ... все не так просто.


[примечание 1]:
это будет иметь место для всех файлов, соответствующих text=auto атрибут (т.е. не имеющий какой-либо другой специализации), поскольку я предполагаю, что ваше репо было правильно нормализовано, когда .gitattribute был создан

Другие вопросы по тегам