Git windows crlf to lf

To avoid problems in your diffs, you can configure Git to properly handle line endings.

About line endings

Every time you press return on your keyboard you insert an invisible character called a line ending. Different operating systems handle line endings differently.

When you’re collaborating on projects with Git and GitHub, Git might produce unexpected results if, for example, you’re working on a Windows machine, and your collaborator has made a change in macOS.

You can configure Git to handle line endings automatically so you can collaborate effectively with people who use different operating systems.

Global settings for line endings

The git config core.autocrlf command is used to change how Git handles line endings. It takes a single argument.

Per-repository settings

Optionally, you can configure a .gitattributes file to manage how Git reads line endings in a specific repository. When you commit this file to a repository, it overrides the core.autocrlf setting for all repository contributors. This ensures consistent behavior for all users, regardless of their Git settings and environment.

The .gitattributes file must be created in the root of the repository and committed like any other file.

A .gitattributes file looks like a table with two columns:

  • On the left is the file name for Git to match.
  • On the right is the line ending configuration that Git should use for those files.

Example

Here’s an example .gitattributes file. You can use it as a template for your repositories:

# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text

# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

You’ll notice that files are matched—*.c, *.sln, *.png—, separated by a space, then given a setting—text, text eol=crlf, binary. We’ll go over some possible settings below.

  • text=auto Git will handle the files in whatever way it thinks is best. This is a good default option.

  • text eol=crlf Git will always convert line endings to CRLF on checkout. You should use this for files that must keep CRLF endings, even on OSX or Linux.

  • text eol=lf Git will always convert line endings to LF on checkout. You should use this for files that must keep LF endings, even on Windows.

  • binary Git will understand that the files specified are not text, and it should not try to change them. The binary setting is also an alias for -text -diff.

Refreshing a repository after changing line endings

After you set the core.autocrlf option or commit a .gitattributes file, Git automatically changes line endings to match your new configuration. You may find that Git reports changes to files that you have not modified.

To ensure that all the line endings in your repository match your new configuration, back up your files with Git, then remove and restore all of the files to normalize the line endings.

  1. Before adding or committing any changes, verify that Git has applied the configuration correctly. For example, Git automatically determines whether files in a repository are text or binary files. To avoid corruption of binary files in your repository, we recommend that you explicitly mark files as binary in .gitattributes. For more information, see gitattributes — Defining attributes per path in the Git documentation.

  2. To avoid losing any local changes to files in the repository, add and commit any outstanding changes by running the following commands.

    Shell
    git add . -u
    git commit -m "Saving files before refreshing line endings"
    
  3. To update all files on the current branch to reflect the new configuration, run the following commands.

    Shell
    git rm -rf --cached .
    git reset --hard HEAD
    
  4. To display the rewritten, normalized files, run the following command.

  5. Optionally, to commit any outstanding changes in your repository, run the following command.

    Shell
    git commit -m "Normalize all the line endings"
    

Further reading

  • Customizing Git — Git Attributes in the Pro Git book
  • git-config in the man pages for Git
  • Getting Started — First-Time Git Setup in the Pro Git book
  • Mind the End of Your Line by Tim Clem

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

Конфигурация Git

В главе Введение кратко упоминалось, что вы можете настроить Git, используя команду git config.
Первое, что вы делали, это установили своё имя и e-mail адрес:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

Сейчас вы познакомитесь с несколькими наиболее интересными опциями, которые можно установить для настройки поведения Git.

Кратко: Git использует набор конфигурационных файлов для изменения стандартного поведения, если это необходимо.
Вначале, Git ищет настройки в файле /etc/gitconfig, который содержит настройки для всех пользователей в системе и всех репозиториев.
Если передать опцию --system команде git config, то операции чтения и записи будут производиться именно с этим файлом.

Следующее место, куда смотрит Git — это файл ~/.gitconfig (или ~/.config/git/config), который хранит настройки конкретного пользователя.
Вы можете указать Git читать и писать в него, используя опцию --global.

Наконец, Git ищет параметры конфигурации в файле настроек в каталоге Git (.git/config) текущего репозитория.
Эти значения относятся только к текущему репозиторию и доступны при передаче параметра --local команде git config.
(Если уровень настроек не указан явно, то подразумевается локальный.)

Каждый из этих уровней (системный, глобальный, локальный) переопределяет значения предыдущего уровня, например, значения из .git/config важнее значений из /etc/gitconfig.

Примечание

Конфигурация Git это обычные текстовые файлы, поэтому можно вручную установить необходимые значения используя соответствующий синтаксис.
Как правило, это проще чем вызывать команду git config для каждого параметра.

Базовая конфигурация клиента

Конфигурационные параметры Git разделяются на две категории: настройки клиента и настройки сервера.
Большая часть — клиентские, для настройки ваших личных предпочтений в работе.
Существует много, очень много настроек, но подавляющее большинство из них применимо только в конкретных случаях; мы рассмотрим только самые основные и самые полезные из них.
Для просмотра полного списка настроек, поддерживаемых вашей версией Git, выполните команду:

Эта команда выведет список доступных настроек с довольно подробным описанием.
Так же, соответствующую документацию можно найти здесь https://git-scm.com/docs/git-config.html.

core.editor

По умолчанию, Git использует ваш редактор по умолчанию ($VISUAL или $EDITOR), если значение не задано — переходит к использованию редактора vi при создании и редактировании сообщений коммитов или тегов.
Чтобы изменить редактор по умолчанию, воспользуйтесь настройкой core.editor:

$ git config --global core.editor emacs

Теперь, вне зависимости от того, какой редактор является основным для вашего окружения, Git будет вызывать Emacs для редактирования сообщений.

commit.template

Если указать путь к существующему файлу, то он будет использован как сообщение по умолчанию при создании коммита.
Смысл создания шаблона сообщения коммита в том, чтобы лишний раз напомнить себе (или другим) о требованиях к формату или стилю оформления сообщения коммита.

Например, предположим что вы создали файл ~/.gitmessage.txt, который выглядит так:

Subject line (try to keep under 50 characters)

Multi-line description of commit,
feel free to be detailed.

[Ticket: X]

Обратите внимание, что шаблон напоминает коммитеру о том, чтобы строка заголовка сообщения была короткой (для поддержки однострочного вывода команды git log --oneline), что дополнительную информацию в сообщении следует располагать ниже, а так же о том, что было бы неплохо при наличии добавить ссылку на номер задачи или сообщения в системе отслеживания ошибок.

Чтобы заставить Git отображать содержимое этого файла в редакторе каждый раз при выполнении команды git commit, следует установить значение параметра commit.template:

$ git config --global commit.template ~/.gitmessage.txt
$ git commit

Теперь, при создании коммита, в вашем редакторе будет отображаться сообщение изменённого вида:

Subject line (try to keep under 50 characters)

Multi-line description of commit,
feel free to be detailed.

[Ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C

Если ваша команда придерживается требований к сообщениям коммитов, то создание шаблона такого сообщения и настройка Git на его использование увеличит вероятность соответствия заданным требованиям.

Данная настройка определяет какая программа будет использована для разбиения текста на страницы при выводе такой информации как log и diff.
Вы можете указать more или любую другую (по умолчанию используется less), а так же выключить совсем, установив пустое значение:

$ git config --global core.pager ''

В таком случае, Git будет выводить весь текст полностью, вне зависимости от его длины.

user.signingkey

Если вы создаёте подписанные аннотированные теги (как описано в разделе Подпись главы 7), то установка GPG ключа в настройках облегчит вам задачу.
Установить ключ можно следующим образом:

$ git config --global user.signingkey <gpg-key-id>

Теперь, вам не нужно указывать ключ для подписи каждый раз при вызове команды git tag:

core.excludesfile

В разделе Игнорирование файлов главы 2 сказано, что вы можете указывать шаблоны исключений в файле .gitignore вашего проекта, чтобы Git не отслеживал их и не добавлял в индекс при выполнении команды git add.

Однако, иногда вам нужно игнорировать определённые файлы во всех ваших репозиториях.
Если на вашем компьютере работает Mac OS X, вероятно вы знакомы с файлами .DS_Store.
Если вы используете Emacs или Vim, то вы знаете про файлы, имена которых заканчиваются на ~ или .swp.

Данная настройка позволяет вам определить что-то вроде глобального файла .gitignore.
Если вы создадите файл ~/.gitignore_global с содержанием:

… и выполните команду git config --global core.excludesfile ~/.gitignore_global, то Git больше не потревожит вас на счёт этих файлов.

help.autocorrect

Если вы ошибётесь в написании команды, Git покажет вам что-то вроде этого:

$ git chekcout master
git: 'chekcout' is not a git command. See 'git --help'.

The most similar command is
    checkout

Git старается угадать, что вы имели ввиду, но при этом команду не выполняет.
Если вы установите help.autocorrect в значение 1, то Git будет выполнять эту команду:

$ git chekcout master
WARNING: You called a Git command named 'chekcout', which does not exist.
Continuing under the assumption that you meant 'checkout'
in 0.1 seconds automatically...

Обратите внимание, что команда выполнилась через «0.1» секунды.
help.autocorrect — это число, указываемое в десятых долях секунды.
Поэтому, если вы установите значение 50, то Git даст вам 5 секунд изменить своё решение перед тем, как выполнить скорректированную команду.

Цвета в Git

Git полностью поддерживает цветовой вывод в терминале, что позволяет быстро и легко визуально анализировать вывод команд.
Существует несколько опций для настройки цветов.

color.ui

Git автоматически подсвечивает большую часть своего вывода, но это можно отключить, если вам не нравится такое поведение.
Для отключения цветового вывода в терминал, выполните следующую команду:

$ git config --global color.ui false

Значение по умолчанию — auto, при котором цвета используются при непосредственном выводе в терминал, но исключаются при перенаправлении вывода в именованный канал или файл.

Вы так же можете установить значение always, что делает вывод одинаковым как в терминал, так и в именованный канал.
Скорее всего, вам это не понадобится; в большинстве случаев, при желании использовать цвета в перенаправленном выводе, указывается флаг --color команде Git для принудительного использования цветовых кодов.
Практически всегда стандартное значение подходит лучше всего.

color.*

Если вы хотите явно указать вывод каких команд должен быть подсвечен и как, Git предоставляет соответствующие настройки.
Каждая из них может быть установлена в значения true, false или always:

color.branch
color.diff
color.interactive
color.status

Каждая из них имеет вложенную конфигурацию, которую можно использовать для настройки отдельных частей вывода при желании переопределить их цвет.
Например, чтобы установить для метаинформации вывода команды diff синий цвет, чёрный фон и полужирный шрифт, выполните команду:

$ git config --global color.diff.meta "blue black bold"

Для установки цвета доступны следующие значения: normal, black, red, green, yellow, blue, magenta, cyan, или white.
Для указания атрибутов текста, как bold в предыдущем примере, доступны значения: bold, dim, ul (подчёркнутый), blink и reverse (поменять местами цвет фона и цвет текста).

Внешние программы слияния и сравнения

Хоть в Git и есть встроенная программа сравнения, которая описывается в этой книге, вы можете установить вместо неё другую.
Вы также можете настроить графический инструмент разрешения конфликтов слияния вместо того, чтобы разрешать конфликты вручную.
Мы покажем как настроить Perforce Visual Merge Tool (P4Merge) для разрешения конфликтов слияния, так как это прекрасный и бесплатный инструмент.

Если у вас есть желание попробовать P4Merge, то она работает на всех основных платформах, так что у вас должно получиться.
В примерах мы будем использовать пути к файлам, которые работают в системах Linux и Mac; для Windows вам следует изменить /usr/local/bin на путь к исполняемому файлу у вас в системе.

Для начала скачайте P4Merge.
Затем, создайте скрипты обёртки для вызова внешних программ.
Мы будем использовать путь к исполняемому файлу в системе Mac; в других системах — это путь к файлу p4merge.
Создайте скрипт с названием extMerge для вызова программы слияния и передачи ей заданных параметров:

$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/p4merge.app/Contents/MacOS/p4merge $*

Скрипт вызова программы сравнения проверяет наличие 7 аргументов и передаёт 2 из них в скрипт вызова программы слияния.
По умолчанию, Git передаёт следующие аргументы программе сравнения:

path old-file old-hex old-mode new-file new-hex new-mode

Так как вам нужны только old-file и new-file, следует использовать скрипт, который передаст только необходимые параметры.

$ cat /usr/local/bin/extDiff
#!/bin/sh
[ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"

Так же следует убедиться, что созданные скрипты могут исполняться:

$ sudo chmod +x /usr/local/bin/extMerge
$ sudo chmod +x /usr/local/bin/extDiff

Теперь можно изменить файл конфигурации для использования ваших инструментов слияния и сравнения.
Для этого необходимо изменить ряд настроек: merge.tool — чтобы сказать Git какую стратегию использовать, mergetool.<tool>.cmd — чтобы сказать Git как запускать команду, mergetool.<tool>.trustExitCode — чтобы сказать Git как интерпретировать код выхода из программы, diff.external — чтобы сказать Git какую команду использовать для сравнения.
Таким образом, команду конфигурации нужно запустить четыре раза:

$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
  'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.extMerge.trustExitCode false
$ git config --global diff.external extDiff

или вручную отредактировать файл ~/.gitconfig добавив соответствующие строки:

[merge]
  tool = extMerge
[mergetool "extMerge"]
  cmd = extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
  trustExitCode = false
[diff]
  external = extDiff

После этого, вы можете запускать команды diff следующим образом:

$ git diff 32d1776b1^ 32d1776b1

Вместо отображения вывода diff в терминале Git запустит P4Merge, выглядеть это будет примерно так:

P4Merge

Рисунок 142. P4Merge

Если при слиянии двух веток у вас возникнут конфликты, выполните команду git mergetool; она запустит P4Merge чтобы вы могли разрешить конфликты используя графический интерфейс.

Используя скрипт обёртку для вызова внешних программ, вы можете легко изменить вызываемую программу.
Например, чтобы начать использовать KDiff3 вместо P4Merge, достаточно изменить файл extMerge:

$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*

Теперь, Git будет использовать программу KDiff3 для сравнения файлов и разрешения конфликтов слияния.

Git изначально настроен на использование ряда других инструментов для разрешения конфликтов слияния, поэтому вам не нужно дополнительно что-то настраивать.
Для просмотра списка поддерживаемых инструментов, выполните команду:

$ git mergetool --tool-help
'git mergetool --tool=<tool>' may be set to one of the following:
        emerge
        gvimdiff
        gvimdiff2
        opendiff
        p4merge
        vimdiff
        vimdiff2

The following tools are valid, but not currently available:
        araxis
        bc3
        codecompare
        deltawalker
        diffmerge
        diffuse
        ecmerge
        kdiff3
        meld
        tkdiff
        tortoisemerge
        xxdiff

Some of the tools listed above only work in a windowed
environment. If run in a terminal-only session, they will fail.

Если вы хотите использовать KDiff3 только для разрешения конфликтов слияния, но не для сравнения, выполните команду:

$ git config --global merge.tool kdiff3

Если выполнить эту команду вместо настройки использования файлов extMerge и extDiff, то Git будет использовать KDiff3 для разрешения конфликтов слияния, а для сравнения — стандартную программу diff.

Форматирование и пробелы

Проблемы форматирования и пробелов являются одними из самых неприятных и незаметных проблем, с которыми сталкивают разработчики при совместной работе, особенно используя разные платформы.
Это легко может произойти с патчами или с любой другой совместной работой, так как редакторы молча исправляют несоответствия, и если ваши файлы когда либо касаются систем Windows, то переносы строк могут быть заменены.
В Git есть несколько настроек, чтобы справиться с этими проблемами.

core.autocrlf

Если вы программируете в Windows и работаете с людьми, которые не используют её (или наоборот), рано или поздно, вы столкнётесь с проблемами переноса строк.
Это происходит потому, что Windows при создании файлов использует для обозначения переноса строки два символа «возврат каретки» и «перевод строки», в то время как Mac и Linux используют только один — «перевод строки».
Это незначительный, но невероятно раздражающий факт кроссплатформенной работы; большинство редакторов в Windows молча заменяют переносы строк вида LF на CRLF или вставляют оба символа, когда пользователь нажимает клавишу ввод.

Git может автоматически конвертировать переносы строк CRLF в LF при добавлении файла в индекс и наоборот — при извлечении кода.
Такое поведение можно включить используя настройку core.autocrlf.
Если у вас Windows, то установите значение true — при извлечении кода LF окончания строк будут преобразовываться в CRLF:

$ git config --global core.autocrlf true

Если у вас система Linux или Mac, то вам не нужно автоматически конвертировать переносы строк при извлечении файлов; однако, если файл с CRLF окончаниями строк случайно попал в репозиторий, то Git может его исправить.
Можно указать Git конвертировать CRLF в LF во время коммита, но не наоборот, установив настройке core.autocrlf значение input:

$ git config --global core.autocrlf input

Такая конфигурация позволит вам использовать CRLF переносы строк в Windows, при этом в репозитории и системах Mac и Linux будет использован LF.

Если вы используете Windows и программируете только для Windows, то вы можете отключить описанный функционал задав значение false, сохраняя при этом CR символы в репозитории:

$ git config --global core.autocrlf false

core.whitespace

Git поставляется настроенным на обнаружение и исправление некоторых проблем с пробелами.
Он в состоянии найти шесть основных проблем, обнаружение трёх из них включено по умолчанию, а трёх других — выключено.

Те, что включены по умолчанию — это blank-at-eol, что ищет пробелы в конце строки; blank-at-eof, что ищет пробелы в конце файла; и space-before-tab, что ищет пробелы перед символом табуляции в начале строки.

Те, что выключены по умолчанию — это indent-with-non-tab, что ищет строки с пробелами вначале вместо символа табуляции (и контролируется настройкой tabwidth); tab-in-indent, что ищет символы табуляции в отступах в начале строки; и cr-at-eol, которая указывает Git на валидность наличия CR в конце строки.

Указав через запятую значения для настройки core.whitespace, можно сказать Git какие из этих опций должны быть включены.
Чтобы отключить ненужные проверки, достаточно удалить их из строки значений или поставить знак - перед каждой из них.
Например, чтобы включить все проверки, кроме space-before-tab, выполните команду (при этом trailing-space является сокращением и охватывает как blank-at-eol, так и blank-at-eof):

$ git config --global core.whitespace \
    trailing-space,-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol

Или можно указать только часть проверок:

$ git config --global core.whitespace \
    -space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol

Git будет искать указанные проблемы при выполнении команды git diff и пытаться подсветить их, чтобы вы могли исправить их перед коммитом.
Так же эти значения будут использоваться во время применения патчей командой git apply.
При применении патчей, можно явно указать Git информировать вас в случае нахождения проблем с пробелами:

$ git apply --whitespace=warn <patch>

Так же можно указать Git автоматически исправлять эти проблемы перед применением патча:

$ git apply --whitespace=fix <patch>

Эти настройки так же применяются при выполнении команды git rebase.
Если проблемные пробелы попали в коммит, но ещё не отправлены в удалённую ветку, можно выполнить git rebase --whitespace=fix для автоматического исправления этих проблем.

Конфигурация сервера

Для серверной части Git не так много настроек, но есть несколько интересных, на которые стоит обратить внимание.

receive.fsckObjects

Git способен убедиться, что каждый объект, отправленный командой push, валиден и соответствует своему SHA-1-хешу.
По умолчанию эта функция отключена; это очень дорогая операция и может привести к существенному замедлению, особенно для больших объёмов отправляемых данных или для больших репозиториев.
Вы можете включить проверку целостности объектов для каждой операции отправки, установив значение receive.fsckObjects в true:

$ git config --system receive.fsckObjects true

Теперь, Git будет проверять целостность репозитория до принятия новых данных для уверенности, что неисправные или злонамеренные клиенты не смогут отправить повреждённые данные.

receive.denyNonFastForwards

Если вы перебазируете коммиты, которые уже отправлены, и попытаетесь отправить их снова или попытаетесь отправить коммит в удалённую ветку, в которой не содержится коммит, на который она указывает, то данные приняты не будут.
В принципе, это правильная политика; но в случае перебазирования — вы знаете, что делаете и можете принудительно обновить удалённую ветку используя флаг -f для команды push.

Для запрета перезаписи истории установите receive.denyNonFastForwards:

$ git config --system receive.denyNonFastForwards true

Сделать то же самое можно другим способом — используя хук на стороне сервера, мы рассмотрим его немного позже.
Этот подход позволяет более гибко настроить ограничения, например, запретить перезапись истории определённой группе пользователей.

receive.denyDeletes

Политику denyNonFastForwards можно обойти, удалив ветку и создав новую с таким же именем.
Для предотвращения этого, установите receive.denyDeletes в значение true:

$ git config --system receive.denyDeletes true

Эта команда запретит удаление веток и тегов всем пользователям.
Чтобы удалить ветку, придётся удалить все соответствующие ей файлы на сервере вручную.
Куда более интересный способ — это настроить права пользователей, с ним вы познакомитесь в разделе Пример принудительной политики Git.

I want to force Git to check out files under Windows using just LF not CR+LF.
I checked the two configuration options, but was not able to find the right combination of settings.

I want to convert all files to have LF line breaks and keep the LF in the files.

Remark: I used autocrlf = input but this just repairs the files when you commit them.
I want to force it to get them using LF.

Probably I wasn’t so clear:
the repository is already using LF but the files checked out using
Git for Windows are using CR+LF
and I want to force Git to get them with LF:
forcing Unix line endings.

$ git config --list | grep crlf
core.autocrlf=input

Henke's user avatar

Henke

4,6013 gold badges31 silver badges45 bronze badges

asked Mar 25, 2010 at 16:07

sorin's user avatar

10

The proper way to get LF endings in Windows is to first set core.autocrlf to false:

git config --global core.autocrlf false

You need to do this if you are using msysgit, because it sets it to true in its system settings.

Now git won’t do any line ending normalization. If you want files you check in to be normalized, do this: Set text=auto in your .gitattributes for all files:

* text=auto

And set core.eol to lf:

git config --global core.eol lf

Now you can also switch single repos to crlf (in the working directory!) by running

git config core.eol crlf

After you have done the configuration, you might want git to normalize all the files in the repo. To do this, go to to the root of your repo and run these commands:

git rm --cached -rf .
git diff --cached --name-only -z | xargs -n 50 -0 git add -f

If you now want git to also normalize the files in your working directory, run these commands:

git ls-files -z | xargs -0 rm
git checkout .

answered Oct 31, 2012 at 8:38

Chronial's user avatar

ChronialChronial

67k14 gold badges93 silver badges99 bronze badges

12

I come back to this question fairly often, though none of its other answers are quite right for me.
That said, the right answer for me is a mixture of the others.

What I find works is the following:

git config --global core.eol lf
git config --global core.autocrlf input

For repos (Git repositories) that were checked out after those global settings were set, everything will be checked out as whatever it is in the repo – hopefully LF (\n).
Any CRLF will be converted to just LF on check-in (commit).

With an existing repo that you have already checked out – that has the correct line endings in the repo but not your working copy – you can run the following commands to fix it:

git rm -rf --cached .
git reset --hard HEAD

This will delete (rm) recursively (-r) without prompt (-f), all files except those that you have edited (--cached), from the current directory (.). The reset then returns all those files to a state where they have their true line endings (matching what’s in the repo).

If you need to fix the line endings of files in a repo, I recommend grabbing an editor that will let you do that in bulk like IntelliJ or Sublime Text, but I’m sure any good one will likely support this.

Henke's user avatar

Henke

4,6013 gold badges31 silver badges45 bronze badges

answered Oct 29, 2015 at 21:24

Ben Liyanage's user avatar

Ben LiyanageBen Liyanage

5,0131 gold badge21 silver badges24 bronze badges

8

The OP added in his question:

the files checked out using msysgit are using CR+LF and I want to force msysgit to get them with LF

A first simple step would still be in a .gitattributes file:

# 2010
*.txt -crlf

# 2020
*.txt text eol=lf 

(as noted in the comments by grandchild, referring to .gitattributes End-of-line conversion), to avoid any CRLF conversion for files with correct eol.

And I have always recommended git config --global core.autocrlf false to disable any conversion (which would apply to all versioned files)

See Best practices for cross platform git config?

Since Git 2.16 (Q1 2018), you can use git add --renormalize . to apply those .gitattributes settings immediately.


But a second more powerful step involves a gitattribute filter driver and add a smudge step

filter driver

Whenever you would update your working tree, a script could, only for the files you have specified in the .gitattributes, force the LF eol and any other formatting option you want to enforce.
If the «clear» script doesn’t do anything, you will have (after commit) transformed your files, applying exactly the format you need them to follow.

answered Mar 25, 2010 at 16:37

VonC's user avatar

VonCVonC

1.3m530 gold badges4436 silver badges5275 bronze badges

6

Context

If you

  1. want to force all users to have LF line endings for text files and
  2. you cannot ensure that all users change their git config,

you can do that starting with git 2.10. 2.10 or later is required, because 2.10 fixed the behavior of text=auto together with eol=lf. Source.

Solution

Put a .gitattributes file in the root of your git repository having following contents:

* text=auto eol=lf

Commit it.

Optional tweaks

You can also add an .editorconfig in the root of your repository to ensure that modern tooling creates new files with the desired line endings.

# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

answered Feb 9, 2017 at 11:52

koppor's user avatar

kopporkoppor

19.2k15 gold badges119 silver badges162 bronze badges

5

core.autocrlf=input is the right setting for what you want, but you might have to do a git update-index --refresh and/or a git reset --hard for the change to take effect.

With core.autocrlf set to input, git will not apply newline-conversion on check-out (so if you have LF in the repo, you’ll get LF), but it will make sure that in case you mess up and introduce some CRLFs in the working copy somehow, they won’t make their way into the repo.

albertjan's user avatar

albertjan

7,5496 gold badges44 silver badges75 bronze badges

answered Apr 1, 2010 at 0:23

kusma's user avatar

kusmakusma

6,5562 gold badges22 silver badges26 bronze badges

1

You can find the solution to this problem at:
https://help.github.com/en/github/using-git/configuring-git-to-handle-line-endings

Simplified description of how you can solve this problem on windows:

Global settings for line endings
The git config core.autocrlf command is used to change how Git handles line endings. It takes a single argument.

On Windows, you simply pass true to the configuration. For example:
C:>git config —global core.autocrlf true

Good luck, I hope I helped.

answered Mar 26, 2020 at 20:54

c-santana's user avatar

1

Время на прочтение
9 мин

Количество просмотров 10K

Я работаю в операционной системе «Windows 10». У меня на компьютере установлена программа «Git for Windows» версии 2.35.1. В принципе, «Git for Windows» — это та же знаменитая программа (набор программ) «Git» (система управления версиями), только скомпилированная из исходного кода в исполняемый файл, который может запускаться в операционных системах «Windows» (изначально исходный код «Git» был написан для компиляции в исполняемый файл, запускаемый в операционной системе «Linux»).

Дистрибутив «Git for Windows» кроме программы «Git» содержит разные полезные для работы с «Git» программы, вроде программы-оболочки «Git Bash» с интерфейсом командной строки и программы «Git GUI» с графическим оконным интерфейсом. В документации сказано, что «Git for Windows» является подмножеством платформы (набора инструментов и библиотек) «MSYS2». Как я понимаю, для компиляции используется компилятор из набора инструментов «MinGW-w64».

Окончания строк в разных операционных системах

Как известно (возможно, не всем), в операционных системах «Windows» окончание строки обычно представляется двумя символами, в таблице Юникода они обозначены кодами U+000D (возврат каретки, по-английски «Carriage Return», сокращенно «CR») и U+000A (подача бумаги на следующую строку, по-английски «Line Feed», сокращенно «LF»). В мир компьютеров эти управляющие коды пришли из мира печатных (пишущих) машинок.

В Unix-подобных операционных системах окончание строки обычно представляется одним символом «LF». (Говорят, в операционных системах от компании «Apple» до появления операционной системы «Mac OS X», которая вышла в 2001 году, окончание строки представлялось одним символом «CR». Сейчас в операционных системах «macOS» окончание строки представляется одним символом «LF», как и в других Unix-подобных операционных системах.)

Из-за того, что большинство текстовых редакторов (даже заточенных под написание текстов программ) плохо умеет работать с окончаниями строк разного вида, вышеописанная разница приносит проблемы, если над одним и тем же проектом работают программисты из разных операционных систем.

Я подготовил для экспериментов текстовый файл, содержащий несколько строк с окончаниями разного вида. Для работы с кодом я обычно использую программы «VS Code» и «Notepad++». Обе эти программы могут правильно отображать строки с окончаниями разного вида. Однако, программа «VS Code» не отображает отдельные символы, входящие в окончания строк, поэтому в ней не получается понять, где и какое окончание строки использовано. Для просмотра и определения видов окончаний строк я обычно использую программу «Notepad++», она умеет отображать отдельные символы, входящие в окончания строк. Вот как у меня на компьютере выглядит в программе «Notepad++» тестовый файл «myfile.txt» (включено отображение всех символов, то есть и тех, которые обычно не отображаются в текстовых редакторах):

На иллюстрации выше видно, что две строки имеют окончания в виде пары символов CR и LF (эту пару символов часто обозначают как «CRLF»), а другие две строки — в виде LF. В программе «Notepad++» у меня не получилось создать разные виды окончаний строк в одном и том же файле (хотя можно скопировать и вставить существующие с помощью инструмента специальной вставки), поэтому я сначала ввел текст файла в программе «Notepad++» с одинаковыми окончаниями строк, а потом подправил два из этих окончаний строк в шестнадцатеричном (двоичном) редакторе. Кодировка файла «myfile.txt» — UTF-8 (как видно на иллюстрации, размер файла — 222 байта, русские буквы занимают по два байта).

Также на иллюстрации выше видно, что в строке состояния программы «Notepad++» режим работы с окончаниями строк показан как «Windows (CR LF)». Этот режим не влияет на отображение символов только что открытого файла. Он лишь говорит о том, что при вставке нового окончания строки (нажатием клавиши «Enter») будет вставлено окончание строки вида CRLF. Этот режим можно переключить на «Unix (LF)» или на «Macintosh (CR)», после чего можно будет клавишей «Enter» вставлять окончания строк вида LF или CR. Однако, переключение этого режима не дает возможности работать в одном файле одновременно с несколькими видами окончаний строк, так как при переключении этого режима меняются сразу все окончания строк в файле на выбранный в режиме вид окончаний строк.

Тестовый файл «myfile.txt» я разместил в папке C:\Users\Илья\source\repos\test\. Пока он в этой папке один. Будем считать эту папку папкой нашего проекта.

Создание Git-репозитория и параметр «core.autocrlf»

С программой «Git» можно работать множеством способов, но я предпочитаю самый универсальный — из командной строки. Для этого я обычно использую программу-оболочку «PowerShell» версии 7, а запускаю ее в программе-«эмуляторе терминала» «Windows Terminal». Итак, проверим, что программа «Git» установлена на компьютере и доступна в папке нашего проекта:

PS C:\Users\Илья\source\repos\test> git --version
git version 2.35.1.windows.2

Создадим Git-репозиторий для нашего проекта:

PS C:\Users\Илья\source\repos\test> git init
Initialized empty Git repository in C:/Users/Илья/source/repos/test/.git/

«Репозиторием» обычно называют папку (хранилище, базу данных), в которой хранится исходный код программы (папку проекта). А «Git-репозиторием» называют базу данных, в которой хранятся разные версии файлов нашего проекта, информация о них и об изменениях, вносимых в эти файлы. Сама программа (система программ) «Git» у меня установлена в папке C:\Program Files\Git\. Чтобы обеспечить управление версиями файлов нашего проекта, в папке нашего проекта с помощью вышеприведенной команды была создана скрытая папка «.git» (у меня в программе «Проводник Windows» включено отображение скрытых папок, поэтому ее там видно), в которой хранятся база данных с версиями файлов нашего проекта и разные служебные файлы.

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

Настройка работы программы «Git» может быть произведена на трех разных уровнях: на уровне операционной системы (для всех ее пользователей), на уровне отдельного пользователя (global) и на уровне проекта (local). При установке программы «Git» программа-установщик обычно задает умолчательные настройки на уровне текущего пользователя операционной системы. В рамках данного поста мы затронем только настройки на уровне текущего проекта, они хранятся в файле \.git\config (этот файл не имеет расширения) текущего проекта. Этот файл был создан в результате вышеприведенной команды «git init», он — текстовый, но нет нужды редактировать его вручную, для этого есть отдельная команда «git config».

Если какой-либо параметр не определен в вышеупомянутом файле настроек текущего проекта, то значение этого параметра будет автоматически взято из файла настроек текущего пользователя операционной системы. Для чистоты эксперимента мы будем прямо прописывать нужное значение нужного параметра в файле настроек текущего проекта с помощью следующей команды:

PS C:\Users\Илья\source\repos\test> git config --local core.autocrlf true

Как работает параметр «core.autocrlf» мы проверим экспериментально, после чего станет понятно, для чего этот параметр можно использовать.

1. Параметр «core.autocrlf», значение «true»

Итак, с помощью команды, приведенной выше, мы установили для параметра «core.autocrlf» значение «true». Совершим первый коммит, в который включим текущую версию нашего тестового файла «myfile.txt»:

PS C:\Users\Илья\source\repos\test> git add "myfile.txt"
warning: LF will be replaced by CRLF in myfile.txt.
The file will have its original line endings in your working directory

PS C:\Users\Илья\source\repos\test> git commit -m "Первый коммит"
[master (root-commit) 4d71045] Первый коммит
 1 file changed, 4 insertions(+)
 create mode 100644 myfile.txt

В блоке кода выше приведены сразу две команды подряд. Команда «git add» формирует список содержимого будущего коммита. Когда содержимое коммита сформировано, делаем сам коммит (регистрацию изменений в коде программы в базе данных в папке «.git» нашего проекта) с помощью команды «git commit».

Два сообщения, выданные после первой команды в блоке кода выше, могут запутать неопытного пользователя. Первое сообщает о том, что окончания строк вида LF будут заменены окончаниями строк вида CRLF в нашем тестовом файле «myfile.txt». Второе сообщает, что версия файла «myfile.txt», находящаяся в папке проекта, сохранит окончания строк в оригинальном виде. На первый взгляд, эти сообщения противоречат друг другу. Путаница возникает из-за того, что в обоих сообщениях употреблено будущее время, но не уточняется, что события, о которых идет речь, хоть и произойдут в будущем, но произойдут НЕ одновременно.

На самом деле, во втором сообщении имеется в виду, что оригинальные окончания строк в файле «myfile.txt» останутся нетронутыми работой запущенной команды «git add». А первое сообщение предупреждает о том, что в будущем, после извлечения версии файла «myfile.txt» из базы данных в папку проекта, окончания строк вида LF будут затерты окончаниями строк CRLF из-за текущего значения настройки «core.autocrlf».

Проверим это на практике. После окончания работы двух команд, показанных в блоке кода выше, я заглянул в файл «myfile.txt», находящийся в папке проекта (в терминах программы «Git» ее называют «рабочей папкой» [working directory], так как именно тут мы работаем с файлами проекта, вносим в них изменения), и убедился, что окончания строк в нем остались без изменений (две строки с окончаниями вида CRLF, две строки с окончаниями вида LF). То есть обещание «The file will have its original line endings in your working directory» сбылось.

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

PS C:\Users\Илья\source\repos\test> git checkout -f master
Already on 'master'

В результате этой команды в папке проекта снова появился файл «myfile.txt». Однако, все четыре окончания строк в этом файле теперь стали одного вида: CRLF. Сбылось обещание из предупреждения «warning: LF will be replaced by CRLF in myfile.txt.».

Как работает настройка «core.autocrlf» со значением «true»? Если при такой настройке мы помещаем версию измененного файла в базу данных «Git» данного проекта, то все найденные в этом файле окончания строк вида CRLF конвертируются в окончания строк вида LF. Если при такой настройке мы извлекаем версию файла, хранящуюся в базе данных «Git» данного проекта, то все найденные в этой версии файла окончания строк вида LF конвертируются в окончания строк вида CRLF. Вот как это можно показать схематично:

  add, commit       База        checkout
-------------->  данных Git  -------------->
 (CRLF -> LF)       (LF)      (LF -> CRLF)

Подчеркну, что на этой схеме внесение в базу данных (коммит) и извлечение из нее (checkout) разнесены во времени. Если внесение в базу данных произошло при настройке «core.autocrlf» со значением «true», а извлечение из базы данных произошло при настройке «core.autocrlf» со значением «false», то конвертация при извлечении не произойдет и все четыре окончания строк в извлеченном файле окажутся вида LF (в том виде, в котором этот файл был помещен в базу данных и хранится там). Это замечание может быть сходным образом применено и к другим значениям настройки «core.autocrlf».

2. Параметр «core.autocrlf», значение «false»

Схема работы при такой настройке:

    add, commit            База             checkout
------------------->    данных Git     ------------------->
 (без конвертации)    (CRLF и/или LF)   (без конвертации)

При такой настройке в базе данных «Git» будет храниться именно то, что мы туда положили. И будет извлечено именно то, что хранится в базе данных, без изменений.

3. Параметр «core.autocrlf», значение «input»

Схема работы при такой настройке:

  add, commit       База          checkout
-------------->  данных Git  ------------------->
 (CRLF -> LF)       (LF)      (без конвертации)

Зачем нужны эти три настройки

Параметр «core.autocrlf» со значением «false» — это естественный режим работы программы «Git», который использовался бы, если б не было разницы в представлении окончаний строк в разных операционных системах.

Собственно, параметр «core.autocrlf» придумали для обеспечения работы над одним проектом программистов из разных операционных систем. Предполагается, что программист в операционной системе «Windows» будет работать с файлами, в которых окончания строк только вида CRLF. При этом предполагается, что он включит для проекта настройку «core.autocrlf» со значением «true». Тогда он будет работать в своей папке проекта с файлами, в которых окончания строк будут вида CRLF, при этом в базе данных «Git» эти же файлы будут сохранены с окончаниями вида LF. Программист в операционной системе «Windows» этого даже не заметит, ведь конвертация происходит автоматически, как было показано выше в пункте 1.

В тот же момент программист в Unix-подобной операционной системе будет работать с той же базой данных «Git», но у него для проекта будет включена настройка «core.autocrlf» со значением «input» (или со значением «false»). Он будет получать из базы данных файлы с окончаниями строк вида LF, как и принято в Unix-подобных операционных системах.

В принципе, программист в операционной системе «Windows» тоже может использовать параметр «core.autocrlf» со значением «false» в случае, если он работает со своей базой данных «Git» один и пишет код только для операционных систем Windows. Либо он работает вместе с другими программистами, но все участники проекта работают в операционных системах «Windows» и проект предназначен только для операционных систем «Windows». Либо, еще один вариант, в коде есть файлы с окончаниями строк разного вида (CRLF и/или LF) и программист хочет сам отслеживать виды окончаний строк в своих файлах, без вмешательства программ, без автоматической конвертации.

Полезные ссылки

  1. В книге «Pro Git» (вторая редакция, вышла в 2014 году), авторы: Scott Chacon (Скотт Чакон) и Ben Straub (Бен Страуб), в главе 8 «Настройка Git», в подглаве 8.1 «Конфигурация Git» (статья большая, ищите в ее последней трети раздел «Форматирование и пробелы»).

  2. Хороший, развернутый ответ на вопрос «Git replacing LF with CRLF» на известном сайте «Stack Overflow».

Git and normalization of line-endings

A few months ago, I spent hours trying to decide about the best way to deal with line endings and how to switch a repo to using .gitattributes. I just found those comprehensive notes, and thought they’d be easier to find here than buried in my notes…

TL;DR

  • line-ending normalization is about converting LF <=> CR+LF, for cross-platform compatibility
  • .gitattributes file is the safest git mechanism to manage line-endings normalization
  • updating normalization settings is tricky because git may report changes on unmodified files, and it is totally not obvious what is happening
  • there are some tricks to help understand what is happening and to fix things

Line endings and Operating systems

When you press <Enter> in your text editor, the file is modified with invisible characters that represent the new line. This invisible thing is most commonly represented in two ways:

  • ASCII character LF (aka Line Feed)
  • ASCII character CR+LF (aka Carriage Return + Line Feed)

Historically, most systems used to require CR+LF, and Unix systems decided in the 1980s to remove the CR character to simplify things and save disk space.

In practice, Windows is the only modern operating systems that still uses CRLF line endings.

When developing in a team, you will end up with people working on Windows and other operating systems, and you will need to manage this difference in your source control system.

Git’s core.autocrlf

This settings is defined via git config. It applies globally or per repo. When enabled, it applies normalization on all files detected by git as text

  1. Checkout Windows-style, commit Unix-style (core.autocrlf=true)

    • Git will convert LF to CRLF when checking out text files.
    • When committing text files, CRLF will be converted to LF.
    • This is the default value pushed by the installer on Windows systems
  2. Checkout as-is, commit Unix-style (core.autocrlf=input)

    • Git will not perform any conversion when checking out text files.
    • When committing text files, CRLF will be converted to LF.
    • some people recommend using this when developing on Unix systems
  3. Checkout as-is, commit as-is (core.autocrlf=false)

    • Git will not perform any conversions when checking out or committing text files.
    • This is default value if the setting is not defined.

Some people consider it is not git’s responsibility to do line-ending normalization. It could be tempting to go «checkout as-is commit as-is» in order to disable git’s normalization. But it cannot be commited to a repo, so it is dependent on developer workstation settings ====> fragile

Regardless of what is defined in people’s local core.autocrlf setting, individual repository maintainers can override the behavior via the .gitattributes file, which is the most robust way to go.

.gitattributes

.gitattributes assigns attributes to file types. The text and eol attributes are used to control the end-of-line normalization process

  • -text : disable normalization for this type of file. Should be used for any type of binary file.
  • text : normalizes this type of file using core.eol, which defaults to OS native (core.eol should not be touched in normal situations)
  • eol=lf : forces lf on all systems, regardless of OS
  • eol=crlf : forces crlf on all systems, regardless of OS

  • global wildcards

    • * text=auto

      • lets git detect file type and apply normalization accordingly
      • similar to setting core.autocrlf=true
    • * -text

      • people have tried to use this to emulate «checkout as-is commit as is»
      • but they had various levels of success
    • you can always use these wildcards in addition to more specific overrides

Beware, line-endings normalization must not be enabled on any binary file.

Updating the normalization settings

If you change the normalization settings (either core.autocrlf or .gitattributes), you will have some work to do on your local repository, on your remote repository, and on your colleagues workstations.

You can also just leave it be, but you expose yourself to weird git behaviors (untouched files reported as changed, among others) or other issues.

Your first reflex would be to look at the line endings in your code editor and play around with the different git commands you’ll find online, but it can very quickly become very confusing.

View the difference between Index and Workspace

You will find quantities of «solutions»/tutorials in stackoverflow or other websites that tell you what to do, but they always miss some edge cases.

Git normalization does not happen in the workspace, but during the transition into or out of the index, so you need a way to view line-endings in both the index and the workspace before acting.

Here is the thing that should be checked to understand what is happening, and most tutorials don’t talk about it:

git ls-files --eol

Enter fullscreen mode

Exit fullscreen mode

Which could result in this type of output:

i/lf    w/crlf  attr/                   Applications/K8S/versions.tf
i/lf    w/lf    attr/text eol=lf        .gitignore
i/-text w/-text attr/                   Services/SMB/hosts-2022-10-20.xlsx
i/lf    w/lf    attr/                   .gitattributes
i/crlf  w/crlf  attr/                   Applications/K8S/ci/backend.tfvars
i/lf    w/crlf  attr/text eol=lf        Legacy/Modules/Keyvault/.gitignore

Enter fullscreen mode

Exit fullscreen mode

  • i/ tells you how the file is saved in the index
  • w/ tells you how the file is presented in the workspace
  • attr/ tells you how the .gitattributes file(s) is (are) hinting git to deal with this file

For a usual Windows developer using the core.autocrlf=true option (which is the default pushed by git installation on Windows), you should normally mostly get a mix of the first three types:

  • i/lf w/crlf attr/ : the file is normalized by git and uses Windows standard line-endings crlf
  • i/lf w/lf attr/text eol=lf : the file is normalized by git and enforced to use lf
  • i/-text w/-text attr/ : the file is autodetected as a binary and not normalized by git

If you ended up with a mix of any other ones, it may be because you or somebody made some changes in the .gitattributes file or the core.autocrlf option.

Repairing i/crlf w/crlf attr/

This file was most probably pushed by someone using core.autocrlf=false and working in Windows. This will typically make git complain about changes on untouched files.

Fix strategies:

  • in any case,

    • make sure your have a clean repo before acting
    • communicate on this change, because people will encounter real conflicts
  • option1: make a commit that will fix all the files in your repo with git add . --renormalize

    • pb: will impede your capability to do a blame
    • you could instruct blame to be more happy with option -w
    • in practice, git GUIs will happily workaround this
    • if necessary you could also use these blame options —ignore-rev, —ignore-revs-file
  • option2: rewrite your history

    • pb: rewriting history is hard.
    • need to synchronize all committers
    • almost impossible in opensource projects

https://www.ofcodeandcolor.com/2013/08/29/normalizing-line-endings-in-git-repositories/
https://www.moxio.com/blog/43/ignoring-bulk-change-commits-with-git-blame

Repairing i/lf w/crlf attr/text eol=lf

In this case, the index is ok, but the workspace is «broken».

This file was probably checked out before attribute eol=lf was specified.
Git will not bother you with this. But maybe your code editor or tool will bug you if it requires crlf line-endings for some file types.

Examples:

  • visual studio may complain or introduce incoherent line-endings if csproj have «wrong» line endings
  • terraform will complain if *.lock.hcl files have wrong line-endings

The fix : delete the local file, and check it out again

Bulk fixing: pipe the output of this command to xargs rm, then do a git reset (with all the precautions needed!!!)

git ls-files --eol | grep "i/lf    w/crlf  attr/t" | cut -f2 -d$'\t'

Enter fullscreen mode

Exit fullscreen mode

Repairing i/lf w/lf attr/text eol=crlf

In this case, the index is ok, but the workspace is «broken».

This time, it may be a problem if your tooling or IDE requires lf line-endings.

The fix: same as the other «broken» workspace situation.

  • Git windows 10 64 bit
  • Git permission denied publickey windows
  • Git update git for windows
  • Git set ssh key windows
  • Git server for windows server