В чем разница между `* text=auto` и `* text eol=lf` in.gitattributes?
Я снова и снова смотрю на документацию .gitattributes но я не могу найти четкого ответа на вопрос, в чем разница между этими двумя:
* text=auto
* text eol=lf
Также text=auto
предназначен только для использования с *
или он также может быть использован с определенными расширениями? В таком случае в чем разница?
*.txt text=auto
*.txt text eol=lf
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
vstext=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
не unsettext
: он оставляетtext
установленным в строковое значениеfalse
. Это имеет тот же эффект, что и оставлениеtext
неопределенным (не конкретно unset). Использование-text
дает ему специальную настройкуunset .Разница между unset
text
и неопределенныйtext
еслиtext
Не указано, Git может попытатьсяугадать -на основе настроекcore.*
, таких какcore.autocrlf
-делать ли преобразования. Когдаtext
конкретно не задано , Git не будет делать никаких предположений: он просто не будет делать никаких преобразований вообще для этого файла.