В чем разница между `* 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файлы в каталоге, и в этом случае они применяются к файлам в этом каталоге и его подкаталогах, но не к путям выше в дереве).Теперь, для
textvstext=auto, а дляeol=lfили нет, мы находим следующее:(Последняя формулировка, на мой взгляд, особенно плоха. Это действительно означает: "из всех паттернов, соответствующих пути, ни один ничего не сказал об этом атрибуте.")Каждый атрибут может находиться в одном из следующих состояний для данного пути:
Набор
Путь имеет атрибут со специальным значением "верно"; это указывается путем перечисления только имени атрибута в поле список атрибутов.
Unset [детали обрезаны, но см. ниже]
Установить значение
Путь имеет атрибут с указанным строковым значением; это указывается путем перечисления имени атрибута с последующим равным знак = и его значение в списке атрибутов.
Неопределенный
Никакой шаблон не соответствует пути, и ничто не говорит, Если путь имеет или не имеет атрибута, атрибут для пути называется быть указано.
Таким образом, для
Эта же логика применима и к элементуtextатрибут установлен, а дляtext=autoатрибут установлен в значение. Частьзначения в этом случае являетсяauto. Поскольку шаблон*, он применяется ко всем файлам.eol=lf. Если, во-первых, этотeol=lfвстречается в некотором шаблоне, а во-вторых, этот шаблон соответствует рассматриваемому файлу, то атрибутeolустанавливается в значение, и значение равноlf. Так как ваша предложенная строка была* text eol=lf, это сделало быeolустановленным в значение и сделало быtextset , но не устанавливается в значение .Если вы пишете, в одном
.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 не будет делать никаких предположений: он просто не будет делать никаких преобразований вообще для этого файла.