В чем разница между autocrlf и eol

Я читаю git documentation о .gitattributes, чтобы исправить мои проблемы со смешанными окончаниями строк и узнать, что есть два аналогичные настройки.

AUTOCRLF:

Преобразование конца строки Хотя Git обычно оставляет содержимое файла отдельно, он может быть настроен на нормализацию окончаний строк в LF в репозитории и, при желании, преобразовать их в CRLF при извлечении файлов.

Если вы просто хотите иметь окончания строк CRLF в своем рабочем каталоге независимо от репозитория, с которым вы работаете, вы можете установить config variable "core.autocrlf" без использования каких-либо атрибутов.

[core] autocrlf = true Это не приводит к нормализации текста файлов, но гарантирует, что текстовые файлы, которые вы вводите в хранилища имеют свои окончания строк, нормированные на LF, когда они добавлены и файлы, которые уже нормализованы в репозитории оставаться нормализованным.

И EOL:

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

Установить строковое значение "crlf" Этот параметр заставляет Git нормализовать строку окончания этого файла при проверке и конвертировать их в CRLF, когда файл выгружен.

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

Обратная совместимость с атрибутом crlfДля обратной совместимости атрибут crlf интерпретируется следующим образом:

crlf text

-crlf -text

crlf = input eol = lf

Кажется, что оба делают то же самое, но есть что-то о compatibility. Означает ли это, что autocrlf устарел и новый вкус eol или что-то еще? В настоящее время у меня есть репозиторий с несколькими поврежденными файлами, которые я хочу преобразовать в представление crlf. И вы видите, что документация путает нас, а не разъясняет вещи.

Что я должен применять в этой ситуации?

Ответ 1

Вместо прямого ответа на сам вопрос - см. ответ VonC на связанный с ним вопрос - давайте сконцентрироваться на этом:

В настоящее время у меня есть репозиторий с несколькими поврежденными файлами, которые я хочу преобразовать в представление crlf.

Во-первых, учтите, что ни один из этих параметров не может изменить любую существующую фиксацию. Это фундаментальное свойство Git: после его создания никакая существующая фиксация не может быть изменена. Что вы можете сделать, это сделать новые коммиты. Обычно это не слишком большая сделка, так как обычно мы просто хотим, чтобы новые вещи были правильными (но см. git filter-branch, которые копируют после применения фильтров к их содержимому и могут быть использованы для повторной копии всего репозитория: новое репо более не совместим со старым, но вы можете "исправить историю" таким образом).

Далее, я думаю, что это ключ к пониманию всех этих атрибутов конца строки /CRLF: преобразования применяются к файлам, когда они перемещаются в индекс или из него.

Помните, что индекс Git - это место, где вы создаете следующую фиксацию. Содержимое индекса вначале совпадает с тем, что текущее значение commit: вы запускаете git checkout master, например, и Git разрешает имя master на идентификатор фиксации и копирует эту конкретную фиксацию в ваше дерево работы - но копия проходит через индекс.

Другими словами, Git сначала обнаруживает, что файл foo.txt находится в commit (и его необходимо извлечь). Таким образом, Git перемещает эту версию foo.txt в индекс. Индексная версия точно соответствует версии HEAD commmit. Git не применяет никаких фильтров к версии индекса и не изменяет никаких окончаний строк.

После обновления индексной версии Git копирует эту версию файла из индекса в рабочее дерево. 1 Некоторые преобразования происходят сейчас, во время этого процесса извлечения. Если есть фильтр смазывания, Git применяет его сейчас. Если есть преобразования конца строки, чтобы сделать, Git применяет их сейчас.

В этом процессе рабочий файл дерева может отличаться от версии индекса. Теперь Git имеет проблему, потому что теперь файл "грязный" (изменен в дереве). Здесь ситуация становится особенно запутанной, хотя большую часть времени детали здесь невидимы.

В конце концов, после работы с вашим деревом, вы можете запустить git add по некоторому имени пути (или использовать git add -a или что угодно, чтобы добавить много файлов). Это копирует файл из дерева работы в индекс. 2 В настоящее время во время этой копии происходят другие преобразования: если есть чистый фильтр, теперь применяется Git. Если есть преобразования конца строки, чтобы сделать, Git применяет их сейчас.

Другими словами, после git add -используя эти файлы, версия индекса может не соответствовать версии рабочего дерева. Однако Git в любом случае отмечает версию индекса как "сопоставление". A git status будет пропущен прямо над версией дерева работ, поскольку Git теперь утверждает, что версия индекса соответствует версии дерева работ. Это похоже на то, что версия индекса соответствует тому, что будет добавлено, если вы снова запустите git add.

Фактическая реализация использует отметки времени, обычно с разрешением в одну секунду. Git будет по-прежнему полагать, что версия индекса соответствует версии рабочего дерева, пока и до тех пор, пока ОС не коснется отметки времени в дереве рабочей версии файла. Это верно, даже если вы измените набор фильтров и/или конверсии окончания строки для применения. Git не понимает, что вы изменили способ окончания строк, или изменили "чистый" фильтр, чтобы сделать что-то другое: он просто видит, что в аспекте "кеш-код" указано "Я отвечаю за время работы дерева -stamp T". Пока метка времени рабочего дерева по-прежнему равна T, файл должен быть "чистым".

Следовательно, чтобы обновить эти вещи после изменения любых параметров преобразования текста, вам нужно сделать Git понять, что файл не чист. Вы можете touch <path> установить новую метку времени "сейчас", которая не будет соответствовать старой отметке времени в индексе. Теперь git add -a (или что-то еще) будет сканировать, как обычно, но поскольку метки времени не совпадают, на этот раз он найдет файл и будет повторно фильтровать его, чтобы добавить его в индекс.

Опять же, эти преобразования происходят, когда вы git add файл.


Как правило, в Windows-подобной системе ваша цель состоит в том, чтобы принимать файлы формата репозитория только в формате LF и превращать их в файлы CR-LF для Windows. Это преобразование происходит на выходе из индекса, в дерево работы: т.е. Во время git checkout. Затем вы захотите преобразовать эти рабочие файлы дерева CR-LF в формат только LF во время процесса git add, так что форма в репозитории будет способом Linux (и Linus Torvalds и, следовательно, Git:-)) предпочитают их. Но вы можете хранить их в репозитории в формате CR-LF, если вы действительно хотите раздражать всех людей Unix/Linux. Все дело в том, какие преобразования, если таковые имеются, вы применяете, при каких шагах: git checkout время и git add время.

Файл .gitattributes указывает, какие преобразования применяются к файлам. Настройки core.autocrlf и core.eol не имеют значения: Git должен наилучшим образом догадываться, какие файлы получают, какие преобразования на каком этапе.


1 Технически, все, что в индексе, является идентификатором хэша файла. Сам файл хранится как объект Git blob в базе данных репозитория. Подобно объектам commit, эти объекты blob являются неизменными. Вот почему он не может быть изменен в индексе: это действительно просто хэш-идентификатор.

2 Процесс git add просто пишет новый blob, с новым блобом, записанным после любой фильтрации. Если новый blob точно соответствует некоторому существующему blob, бит-бит, новый blob повторно использует существующую запись базы данных blob и идентификатор хэша и фактически не сохраняется - существующего blob хватает. Если нет, данные blob сохраняются в виде нового файла с новым идентификатором. Это новый идентификатор хэша, который входит в индекс.