Следите за концом строки

Один из самых частых вопросов о Гите — почему так сложно работать с окончаниями строк. В этой статье мы попробуем ответить на этот вопрос и рассказать о множестве опций и настроек для контроля над окончаниями строк в Гите.
Гит имеет дело с двумя системами для работы с концами строк в репозиториях. Корень проблемы в том, что популярные операционные системы по-разному обозначают конец строки: Unix, Linux и Mac OS X используют LF , а Windows CRLF . В этой статье мы не будем брать во внимание, что в предыдущих версиях Mac OS X использовался CR .
Ничего из этого не было бы проблемой, если бы каждый из нас жил в своём маленьком, изолированном мире и никогда не обменивался кодом между разными операционными системами. Под обменом кодом, в данном случае, будем понимать всё — от работы над кросс-платформенным проектом до копирования кода из браузера. Всякий раз, когда вы скачиваете архив проекта с Гитхаба, копируете код из чьего-то блога или гиста или используете код из файла на облачном хранилище, вы работаете с текстом, а значит имеете дело с невидимыми символами окончаний строк.
Все эти действия с кодом потенциально могут привнести разные настройки окончаний строк в вашу кодовую базу. Это может привести к беспорядочным диффам и сделать работу с Гитом в целом неприятной.
Основное решение, которое принял Гит для этой проблемы — указать, что лучший способ хранить окончания строк в репозитории для текстовых файлов — использование LF . Это правило ни к чему вас не принуждает, но большинство разработчиков, использующих Гит и Гитхаб, приняли его как соглашение и мы тоже рекомендуем так настроить ваш конфиг.
Основы
Перед тем, как мы опишем настройки для управления окончаниями строк, нам надо узнать несколько вещей о core.eol и разобраться с тем, что значит записать что-либо в базу данных Гит.
Конец строки
core.eol — первый параметр, о котором нужно знать.
Почти всегда, кроме самых редких случаев, нам не стоит менять дефолтное значение этого параметра. Хотя сам по себе core.eol мало что делает, нам нужно знать его значение каждый раз, когда мы хотим, чтобы Гит изменил окончания строк. Так как этот параметр будет использоваться во всём, о чём пойдёт речь дальше, хорошо бы знать о его существовании и о том, что его значение, вероятно, менять не придётся.
- core.eol = native — значение по умолчанию. При записи файла в рабочую папку, Гит изменит окончания строк на соответствующие вашей платформе по умолчанию. Для Windows это будет CRLF , для Unix, Linux и Mac OS X — LF ;
- core.eol = crlf — если установлено такое значение, Гит всегда будет использовать для обозначения конца строки CRLF при записи файла в вашу рабочую директорию;
- core.eol = lf — это значение скажет Гиту всегда использовать LF для обозначения конца строки при записи файла в вашу рабочую папку.
Чтобы узнать, какое значение core.eol установлено в вашей системе, нужно запустить в консоли команду git config —global core.eol . Если команда ничего не вернёт, значит, в вашей системе используется значение по умолчанию, native .
Запись и вывод объектов из базы данных
Прежде чем двигаться дальше, мы поговорим о двух важных операциях: записи в объектную базу и выводе данных из неё в рабочую директорию. Возможно, вы уже знаете, что Гит хранит свою базу данных в папке .git . Он создаёт эту директорию и несколько файлов в ней, после запуска команды git init . Файлы в папке .git определяют все конфигурации Гита, в них хранится история проекта. Это обычные файлы и мы можем их читать и редактировать так же, как файлы самого проекта.
Каждый раз, когда мы делаем команду типа git commit , мы записываем объекты в эту базу данных. Запись в базу данных включает в себя:
- сохранение всего содержимого файла;
- добавление его в список со всеми файлами, которые отслеживает Гит;
- создание блоб-файла;
- вычисление SHA-ключа — хэш-кода, в котором хранится информация о содержимом файла.
Во время записи в базу данных **Гит может запустить фильтры и преобразовать окончания строк.
Есть ещё один случай, когда у Гита появляется возможность преобразовать окончания строк — это запись файлов из базы данных в нашу рабочую папку. Это то, что мы подразумеваем под выводом из базы данных. Такой процесс можно запустить множеством команд, но самая очевидная и простая для понимания — git checkout . Вывод из объектной базы данных также происходит после запуска команд, которые делают изменения в нашей рабочей папке, например, git clone или git reset .
Старая система
Теперь давайте поговорим о старой системе — оригинальном наборе функций в Гите, предназначенном для решения конкретной проблемы с окончаниями строк. Есть большая вероятность, что вы прямо сейчас пользуетесь старой системой и даже не подозреваете об этом.
Вот как это работает: у Гита есть настройка конфигураций core.autocrlf , которая специально создана для того, чтобы все окончания строк в текстовом файле преобразовывались в LF при записи в объектную базу данных репозитория. Вот список разных настроек для core.autocrlf и их значений:
- core.autocrlf = false — это значение по умолчанию, которое большинству людей следует сменить. Результатом использования этого значения станет то, что Гит не будет связываться с окончаниями строк в ваших файлах. Там могут быть разные окончаниями строк: LF , CRLF , CR или микс из всех них, но Гиту это будет безразлично. Такое значение может привести к тому, что диффы станут менее читаемыми и появятся сложности при слиянии веток. У большинства пользователей Unix/Linux установлено именно это значение, потому что у них нет проблем с CRLF и им не нужно, чтобы Гит делал дополнительную работу каждый раз при записи файлов в базу данных или в рабочую папку.
- core.autocrlf = true — значит, что Гит обработает все текстовые файлы и убедится, что все CRLF заменены на LF перед записью в базу данных. При обратном процессе он преобразует все LF в CRLF . Такая установка гарантирует, что ваш репозиторий можно будет использовать на других платформах, сохраняя CRLF в вашем рабочей папке. Поэтому параметр true для core.autocrlf рекомендован для Windows.
- core.autocrlf = input — значит, что Гит обработает все текстовые файлы и убедится, что все CRLF изменены на LF при записи файлов в базу данных. Однако обратной замены не произойдёт. При записи файлов в рабочую папку из базы данных, для обозначения конца строки останутся LF . Этот параметр обычно используется в Unix / Linux / OS X для предотвращения записи CRLF в репозиторий. Идея заключается в том, что если вы вставили код из браузера и случайно записали CRLF в один из ваших файлов, Гит удостоверится, что произойдёт замена на LF при записи в базу данных.
Чтобы увидеть, какое значение для core.autocrlf установлено в вашей системе, нужно запустить в командной строке git config —global core.autocrlf . Если команда ничего не вернёт, то вы используете значение по умолчанию, false .
Как же Гит определяет, что файл текстовый? Хороший вопрос. У Гита есть внутренний эвристический метод, который проверяет, двоичный ли файл. Если файл не двоичный, то Гит считает его текстовым. Но Гит иногда может ошибаться, и это будет причиной для знакомства со следующей настройкой.
Параметр core.safecrlf был создан на тот случай, если Гит ошибётся и изменит окончания строк там, где лучше было бы оставить их в покое.
- core.safecrlf = true — перед записью в базу данных при подготовке к замене CRLF на LF , Гит убедится, что сможет успешно прервать операцию. Он проверит, что можно откатить изменения (из LF в CRLF ), а если нет, то отменит операцию.
- core.safecrlf = warn — сделает то же, что и предыдущий параметр, но вместо того, чтобы прервать операцию, Гит просто предупредит вас о том, что может случиться что-то нехорошее.
Наконец, вы можете создать в корне своего репозитория файл .gitattributes и указать в нём настройки для конкретных файлов. Это позволит вам управлять такими настройками, как autocrlf для каждого типа файлов.
Например, для того, чтобы Гит заменил CRLF на LF во всех текстовых файлах, можно написать в .gitattributes такую строку:
Или можно сделать, чтобы Гит никогда не заменял CRLF на LF в текстовых файлах с помощью такой строки:
Чтобы Гит заменял CRLF на LF в текстовых файлах только при записи в базу данных, но возвращал LF при записи в рабочий каталог, нужно написать:
Хорошо, видите, какой беспорядок мы тут учинили? И он становится ещё больше, если мы начинаем работать над проектами, которые подталкивают нас к другим глобальным настройкам. Введём в дело новую систему, доступную начиная с версии Гит 1.7.2.
Новая система
Новая система определяет все настройки для окончаний строк в файле .gitattributes вашего репозитория, инкапсулируя их внутри и делая независимыми от глобальных настроек.
В новой системе за то, чтобы указать Гиту, в каких файлах надо заменить CRLF на LF , отвечаете вы, сообщая об этом с помощью атрибута text в файле .gitattributes . В этом случае будет полезен мануал для .gitattributes , а ниже вы найдёте несколько примеров использования атрибута text .
- *.txt text — устанавливает атрибут text для всех текстовых файлов. Это значит, что Гит будет запускать процесс замены CRLF на LF каждый раз при записи в БД и делать обратную замену при выводе из базы данных в рабочий репозиторий.
- *.txt -text — снимет со всех текстовых файлов этот фильтр. Это значит, что в указанных файлах не будет замены CRLF на LF .
- *.txt text=auto — установит для всех, подходящих под условие файлов, замену CRLF на LF , если Гит с помощью своего эвристического метода определит эти файлы как текстовые, а не бинарные.
Если файл не определён, Гит вернётся к старой системе и настройке core.autocrlf .
Именно так работает обратная совместимость, но я рекомендую, особенно тем, кто использует Windows для разработки, явно создавать файл gitattributes.
Ниже пример файла .gitattributes с общими настройками, который можно использовать для своего проекта. Пример взят отсюда.
Как вы могли заметить, с помощью следующей команды можно сказать Гиту обнаруживать все текстовые файлы и автоматически конвертировать в них CRLF в LF :
Важно ли сообщение «LF will be replaced by CRLF in» или можно не обращать внимания?
Привет всем! Помогите разобраться с этим сообщением Git . я так понял этим вопросом задаются все, кто только начал изучать его и я не исключение ) Разбирался, читал, но похоже только больше ещё запутался, что во что конвертируется и в целом нужно ли на это обращать внимание.
Дело такое: я работаю на Виндовс 7, через Git Bash . и в самом Git Bash создал файл .gitignore. Как я понял Git Bash это линуксовая консоль, поэтому она создает файлы с LF.
Поэтому, когда я выполнил команду git add , то появилось это предупреждение: warning: LF will be replaced by CRLF in .gitignore.
Я пытался разобраться самостоятельно, пробовал как в документации прописывал autocrlf = true, но сообщение всё равно появляется.
Поэтому прошу, помогите разобраться . к примеру, если я планирую кросс-платформенную работу над проектом, стоит ли обращать на это сообщение внимание и правильно ли я прописал autocrlf = true (если нет, то как будет правильно)?
- Вопрос задан более двух лет назад
- 4492 просмотра
- Вконтакте
- Вконтакте
Senseich,
autocrlf = true преобразование в crlf, так как принято в Windows,
autocrlf = input преобразование в lf, как принято в Linux,
autocrlf = false не использовать преобразование, а сохранять файл как есть.
Влияют ли или нет переводы на чтото, вам виднее, я же не знаю, что вы храните. Но в любом случае, лучше выбрать тот или иной способ перевода строк, как стандартный для проекта, особенно, если разработчики используют разные платформы. Просто для того, чтобы при сравнении файлы не отличались из-за переводов, хотя современные средства легко игнорируют такие различия, но файл все равно будет фигурировать в git, как измененный.

Vitsliputsli, точнее, насколько я понимаю,
true — CRLF→LF при коммите, LF→CRLF при чекауте;
input — только CRLF→LF при коммите;
false — коммитится и чекаутится, да, как есть.
Lf will be replaced by crlf что это

При выполнении команды git add . у Вас может возникнуть подобная ошибка. Давайте разберемся почему это происходит и как это исправить.
Итак, полностью ошибка может выглядеть следующим образом:
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in path/to/the/file.
Здесь всего-лишь говорится, что перенос строки будет дополнен возвратом каретки.
Если Вы работаете под ОС Linux или Mac OS, то убрать предупреждения можно этой командой:
$ git config —global core.autocrlf input
Если Вы работаете в Git один под Windows и просто хотите выключить эти предупреждения, то введите следующую команду:
git config core.autocrlf true
git config —global core.autocrlf true
Но по-правильному дожно быть так:
$ git config —global core.autocrlf false
Связанно это может быть с тем что переносы строк были в Unix-формате, когда дело происходило под Windows, например. Очень просто конвертировать переносы строк в Windows-формат помогает текстовый редактор Notepad++: Правка→EOL конверсия→Преобразовать в WIN-формат.