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

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

АВТОКРЛФ:

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

Если вы просто хотите, чтобы в вашем рабочем каталоге были окончания строк CRLF независимо от репозитория, с которым вы работаете, вы можете установить переменную конфигурации «core.autocrlf» без использования каких-либо атрибутов.

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

И ЭОЛ:

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

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

Установите строковое значение «lf». Этот параметр заставляет Git нормализовать окончания строк до LF при возврате и предотвращает преобразование в CRLF при извлечении файла.

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

crlf текст

-crlf -текст

crlf=ввод eol=lf

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

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


person Alex Zhukovskiy    schedule 20.02.2017    source источник
comment
Этот вопрос похож, но я не уверен, что это дубликат. С другой стороны, ответ VonC объясняет разницу между core.eol и core.autocrlf довольно подробно.   -  person Sascha Wolf    schedule 20.02.2017


Ответы (1)


Вместо прямого ответа на сам вопрос — см. ответ VonC на связанный вопрос — давайте сосредоточимся на этом:

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

person torek    schedule 20.02.2017
comment
Отличный ответ, но core.autocrlf в настройках gitattributes и eol (*.txt text eol=crlf) предназначены именно для этой проблемы - преобразования EOL во время извлечения и добавления в index. Меня просто смутили две настройки для одного и того же. После некоторых исследований я обнаружил, что последний параметр просто позволяет более точную настройку. Вы настраиваете файлы по расширению, а не для всех файлов в репозитории. autocrlf уже повредил некоторые файлы в моем репозитории (например, xls), когда я могу пометить их как binary с помощью eol - person Alex Zhukovskiy; 21.02.2017
comment
Если вы используете *.blah text=auto, то да, вы делаете это по расширению (и автоклассификации). Если вы используете foo.* text=auto, вы делаете это по префиксу, а если вы используете * text=auto, вы явно вызываете его глобально, а не зависите от core.autocrlf (чья настройка находится вне файлов, контролируемых Git в репозитории). Я думаю, что тот факт, что core.autocrlf не является частью файлов с контролем версий, может быть ключевой причиной для его использования или избегания (лично я избегаю его так же, как избегаю Windows :-)). - person torek; 21.02.2017
comment
Я ожидал, что core.autocrlf можно хранить в gitattributes так же, как text=.... Однако я не пробовал и остановился на новом блестящем эоле. - person Alex Zhukovskiy; 21.02.2017
comment
@AlexZhukovsky: нет, core.autocrlf — это настройка git config, и их нельзя хранить в репозитории. - person torek; 21.02.2017
comment
Ладно, я понял. Тогда последний вопрос: есть ли здесь разница между настройками -text и binary? Потому что я нашел первый на странице документации git, а второй используется в каждом .gitattributes, который я вижу. - person Alex Zhukovskiy; 21.02.2017
comment
Согласно документам gitattributes, binary — это макрос, который расширяется до -text -diff. Это не имеет прямого отношения, но есть два места, где литеральная строка binary имеет смысл: внутри драйвера сравнения (см. обсуждение в конце раздела textconv) и в качестве драйвера слияния (см. Встроенные драйверы слияния). - person torek; 21.02.2017