В чем разница между `* text=auto` и `* text eol=lf` in.gitattributes?


Я снова и снова смотрю на документацию .gitattributes но я не могу найти четкого ответа на вопрос, в чем разница между этими двумя:

* text=auto

* text eol=lf

Также text=auto предназначен только для использования с * или он также может быть использован с определенными расширениями? В таком случае в чем разница?

*.txt text=auto

*.txt text eol=lf

1 3

1 ответ:

TL; DR

Параметр eol=lf переопределяет любой параметр text, и поскольку вы решили применить его к каждому пути, только параметр eol=lf будет иметь значение, если вы его используете.

Полное объяснение

Давайте начнем с этого и будем работать вовне:

Также text=auto предназначен только для использования с * или он также может быть использован с определенными расширениями?

Паттерны могут включать в себя расширения. Часть text=auto является атрибутивной установкой , и шаблоны выбирают, какие атрибуты применять к какому файлу(файлам).

Как Git читает файл .gitattributes

Каждая строка в .gitattributes соответствует или не соответствует некоторому имени пути, такому как dir1/dir2/file.ext или README.md или что угодно. Как в документации gitattributes говорится:

Каждая строка в файле gitattributes имеет вид:

pattern attr1 attr2 ...

То есть шаблон, за которым следует список атрибутов, разделенный пробелами. Начальные и конечные пробелы игнорируются. Строки, которые начинаются с # игнорируются. Шаблоны, начинающиеся с двойной кавычки, цитируются в стиле Си. Если шаблон соответствует указанному пути,то ему присваиваются атрибуты, перечисленные в строке.

Следовательно, * являетсяпаттерном . Эти "паттерны" такие же, как и в файлах .gitignore , за исключением того, что отрицательные паттерны запрещены. Таким образом, вы можете использовать шаблоны типа *.txt и *.jpg для сопоставления расширений имен файлов, или шаблоны типа dir1/* для сопоставления файлов внутри определенного файла. каталог (хотя есть и другой способ сделать это: как .gitignore файлы, вы можете иметь .gitattributes файлы в каталоге, и в этом случае они применяются к файлам в этом каталоге и его подкаталогах, но не к путям выше в дереве).

Теперь, для text vs text=auto, а для eol=lf или нет, мы находим следующее:

Каждый атрибут может находиться в одном из следующих состояний для данного пути:

  • Набор

    Путь имеет атрибут со специальным значением "верно"; это указывается путем перечисления только имени атрибута в поле список атрибутов.

  • Unset [детали обрезаны, но см. ниже]

  • Установить значение

    Путь имеет атрибут с указанным строковым значением; это указывается путем перечисления имени атрибута с последующим равным знак = и его значение в списке атрибутов.

  • Неопределенный

    Никакой шаблон не соответствует пути, и ничто не говорит, Если путь имеет или не имеет атрибута, атрибут для пути называется быть указано.

(Последняя формулировка, на мой взгляд, особенно плоха. Это действительно означает: "из всех паттернов, соответствующих пути, ни один ничего не сказал об этом атрибуте.")

Таким образом, для text атрибут установлен, а для text=auto атрибут установлен в значение. Частьзначения в этом случае является auto. Поскольку шаблон *, он применяется ко всем файлам.

Эта же логика применима и к элементу eol=lf. Если, во-первых, этот eol=lf встречается в некотором шаблоне, а во-вторых, этот шаблон соответствует рассматриваемому файлу, то атрибут eol устанавливается в значение, и значение равно lf. Так как ваша предложенная строка была * text eol=lf, это сделало бы eol установленным в значение и сделало бы text set , но не устанавливается в значение .

Если вы пишете, в одном .gitattributes файле, то две строки последовательность :

* text=auto
* text eol=elf

Вторая строка text переопределяет первую, так что text устанавливается (но не в значение), а eol устанавливается в значение, причем значение равно lf. Обе линии совпадали, и вторая перекрывала первую.

Если вы перевернете две строки:

* text eol=lf
* text=auto

Затем снова обе строки совпадают , но теперь вторая строка только переопределяет настройку text, поэтому теперь у вас есть text, установленный в auto и eol, установленный в lf.

Как атрибут text применяется к файлам

Следующий раздел gitattributes по документации говорит:

Этот атрибут [text] включает и контролирует нормализацию конца строки. ... [Если это так]

  • Набор ... включает нормализацию конца строки и помечает путь как текстовый файл ...

  • Унсет ... говорит Git не пытаться выполнить любое преобразование конца строки при регистрации или оформлении заказа ...

  • Установите в строку значение "auto"... Если Git решит, что содержание-это текст ...

  • Не указано ... Git использует переменную конфигурации core.autocrlf...

(что означает, что вы должны пойти искать документацию git config , чтобы узнать, что core.autocrlf делает, если вы оставите text неопределенным).

Вы выбрали либо установить его для каждого файла, либо установить его в auto для каждого файла. Первое означает " делать преобразование для каждого файла" и последнее-настройка auto - означает: Эй, ГИТ, пожалуйста, реши для меня, является ли файл текстом или нет. Если вы решили, что это текст, выполните преобразование.

Как eol=lf применяется к файлам

Чуть ниже описания параметра text приведено описание параметра eol:

Этот атрибут задает определенный стиль окончания строки, который будет использоваться в рабочий каталог. Он позволяет осуществлять конвертацию в конце строки без каких-либо проверяет содержимое, эффективно устанавливая атрибут text.

  • Установите строковое значение "crlf"... [отрезано, потому что вы установили lf]

  • Установить строковое значение " lf "

    Эта настройка заставляет Git нормализовать концы линий к LF на проверка и предотвращает преобразование в CRLF, когда файл проверенный.

Итак, если у вас есть eol=lf Набор для пути-и с * в качестве шаблона, он будет установлен для каждый path-Git будет рассматривать каждый файл как текст и выполнять преобразование из CR-LF-окончаний строк в LF-только окончания строк на "checkin" (опять же, это плохо сформулировано: преобразование фактически происходит на этапе git add). Git ничего не будет делать во время проверки (это тоже не совсем точно сформулировано: преобразование-или в данном случае неконверсия-происходит во время извлечения из индекса в рабочее дерево).

Если вы используете разные шаблоны, вы получаете разные результаты

Обратите внимание, что если вы выберите шаблон типа *.txt, затем эти атрибуты устанавливаются только для путей, соответствующих шаблону. Для других путей эти атрибуты остаютсяunset . Поэтому вы должны посмотреть назад надокументацию и посмотреть, что происходит, когда эти атрибуты не заданы.

Можно, конечно, сделать так:

* -text
*.txt eol=lf

Первая строка будет явно unset text на всех файлах, оставляя eol неуказанным на всех файлах. Затем вторая строка устанавливает к значению eol=lf для файлов *.txt переопределение неопределенного значения. Теперь Git будет применять правила eol=lf ко всем файлам, имя которых совпадает с *.txt, и использовать неуказанные правила-eol и unset-text для всех остальных файлов.

Этот специальный синтаксис -text - материал, который я вырезал выше. Использование text=false не unset text: он оставляет text установленным в строковое значение false. Это имеет тот же эффект, что и оставление text неопределенным (не конкретно unset). Использование -text дает ему специальную настройкуunset .

Разница между unset text и неопределенный text если text Не указано, Git может попытатьсяугадать -на основе настроек core.*, таких как core.autocrlf-делать ли преобразования. Когда text конкретно не задано , Git не будет делать никаких предположений: он просто не будет делать никаких преобразований вообще для этого файла.