Як працюють конверсії рядків, що закінчуються, з git core.autocrlf між різними операційними системами


220

Я прочитав багато різних питань та відповідей щодо переповнення стека, а також документацію на git про те, як працює налаштування core.autocrlf .

Це моє розуміння з того, що я прочитав:

Клієнти Unix та Mac OSX (до 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 у коментарях, я змінив деякі значення у "невідомі" значення у таблиці вище, а також змінив "замовлення існуючих | true для конвертування до CRLF замість перетворення на клієнта ". Ось такі визначення, які він дає, які більш чіткі, ніж усе, що я бачив деінде:

core.autocrlf = хибний

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

core.autocrlf = вірно

Це означає, що 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. В даний час у мене глобальний git config встановлений core.autocrlf = вхід. Чи добре я їхати? Чи колись у мене буде конфлікт?
Кріс

Відповіді:


128

Найкраще пояснення того, як core.autocrlfроботи знаходяться на сторінці gitattributes man, у розділі textатрибутів.

Ось як, core.autocrlfздається, працює зараз (або принаймні з версії 1.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 EOL - LFу робочих деревах.
    3. gitattributesНалаштування репозиторію визначає нормалізацію символів EOL для комісій у сховище (за замовчуванням - це нормалізація LFсимволів).

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


3
для autocrlf = true не повинно бути таким? Текстові файли, у яких у сховищі є лише символи CRLF EOL, нормалізуються з CRLF в LF, коли повертаються назад у сховище. Файли, що містять LF у сховищі, будуть недоторкані.
Пьотр Левандовський

2
Для мене, навіть якщо autocrlf = false git перетворював EOL в CRLF. Прочитавши цю відповідь, я зрозумів, що мій файл .gitattribute має текст = автоматичний набір, що спричиняє проблеми.
irsis

1
Бо core.autocrlf = falseякщо я не маю gitattributesфайлу, чи означає це, що не буде нормалізації? Або це означає, що він буде використовувати нормалізацію за замовчуванням?
Підборіддя

Чи не повинен .gitattributesфайл мати перевагу над core.autocrlfналаштуваннями?
Qwerty

63

Проблема ЗНО в проектах зі змішаними платформами вже давно робить моє життя жалюгідним. Проблеми, як правило, виникають, коли вже є файли з різними та змішаними EOL, які вже є у репо. Це означає що:

  1. Репо може мати різні файли з різними EOL
  2. Деякі файли репо можуть мати змішаний EOL, наприклад, комбінацію CRLFта LFв одному файлі.

Як це відбувається, тут не питання, але це трапляється.

Я провів декілька тестів на перетворення в Windows для різних режимів та їх комбінацій.
Ось що я отримав у трохи зміненій таблиці:

                 | Результат перетворення, коли | Результат конверсії, коли
                 | створення файлів з різними | перевірка від РЕПО -
                 | EOLs INTO repo та | із змішаними файлами в ньому та
                 | 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 випадок, коли конверсія відбувається, коли:

  1. core.autocrlfє true і
  2. файл у репо має LFEOL.

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

Зауважте також, що "старі" Mac EOL CRлише також ніколи не конвертуються.
Це означає, що якщо неправильно написаний сценарій перетворення EOL намагається перетворити змішаний кінцевий файл з CRLFs + LFs, просто перетворивши LFs в CRLFs, то він залишить файл у змішаному режимі з "одиноким" CRs, де б не CRLFбув перетворений CRCRLF.
Git тоді нічого не перетворить, навіть у trueрежимі, і хаос EOL продовжується. Це насправді трапилося зі мною і дуже погано переплутало мої файли, оскільки деякі редактори та компілятори (наприклад, VS2010) не люблять Mac EOL.

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


4
Відмінна відповідь, але одне речення, з яким я не можу погодитись - це у Windows, імовірно, відновити роботуcore.autocrlf true . Я особисто вважаю, що його inputслід використовувати завжди.
Г. Демецький

39

Речі мають змінитись на фронті "eol convert" з майбутнім Git 1.7.2 :

Нове налаштування конфігурації core.eolдодається / змінюється :

Це заміна для "додавання" core.eol"змінної конфігурації", яка знаходиться зараз 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впливу на еол:

Див фіксації 817a0c7 (23 Feb 2016), здійснюють 6e336a5 , здійснюють df747b8 , здійснюють df747b8 (10 Feb 2016), здійснюють df747b8 , здійснюють df747b8 (10 Feb 2016), а також здійснювати 4b4024f , здійснюють bb211b4 , здійснюють 92cce13 , здійснюють 320d39c , здійснюють 4b4024f , commit bb211b4 , commit 92cce13 , commit 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)

Як додає Торек у коментарях :

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

Детальніше про це дивіться у розділі " Яка різниця між autocrlf та eol ".


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 ... :-)
torek

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.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: нічого не відбувається, енн для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 = вхід: нічого не відбувається
    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

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  
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.