In Linux, lines end with LF (Line Feed, \n
), while in Windows, CRLF (Carriage Return + Line Feed, \r\n
). When developers using different operating systems contribute to the same Git project, line endings must be handled correctly, or diff
and merge
may break unexpectedly. Git provides several solutions to this problem, including configuration options and file attributes.
TL;DR
Approach 1
Set core.autocrlf
to input
in Windows. Leave Linux/macOS unchanged.
1 | git config --global core.autocrlf input |
Approach 2
Create .gitattributes
under the project root, and add the following line:
1 | * text=auto eol=lf |
Use consistent line endings
I suggest using LF in all OSes. Modern editors are capable of recoganizing and handling line endings across platforms. Even Notepad in Windows 10 can display text files with LFs correctly. Usually we have an .editorconfig
file in the project, so that various editors with plugin installed will behave the same when handling line endings, as well as charset and indent.
1 | root = true |
This consistency also lies in Git itself. When you enable Git to handle line endings for you, either by core.autocrlf
or .gitattributes
, Git always stores LFs in the repository.
The classic core.autocrlf
option
core.autocrlf
has three options:
false
The default value, meaning Git will not touch the files when checking in or out of the repository. Check-in means committing files to the repository; check-out means writing to the working directory.true
Git will convert LF to CRLF when checking out of the repository, and convert them back to LF when checking in.input
Git checks out the files as-is, and converts CRLF to LF when checking in.
When core.autocrlf
is set to input
, Git will give you a warning when adding text files with CRLF endings:
1 | warning: CRLF will be replaced by LF in test.txt. |
Only text files will be processed by Git, but sometimes Git may mistakenly treat binary files as text files and corrupt the data by replacing CRLF with LF. So Git provides a core.safecrlf
option that checks if it can convert LF back to CRLF and produce the exact same file content. If it is not the case, Git rejects this operation with an error:
1 | fatal: LF would be replaced by CRLF in test.bin |
This setting also causes problem when you have a mixture of LF and CRLF in one file, because Git will detect that it cannot reproduce the original file when checking out. In this case, line endings need to be fixed manually.
Configure end-of-line in Git attributes
There are two caveats in the core.autocrlf
approach. First, it is a configuration that needs to be set manually by every developer, either globally or locally. Second, it may corrupt binary files. So newer version of Git provides the attribute mechanism, that saves configurations into a file named .gitattributes
, and just like .editorconfig
, this file should be checked into the repository so that all developers may share the same config. Git attributes also support path wildcards, so users can specify which files should be processed as text files. For instance:
1 | # Auto detect file types, if no further configs are given. Set end-of-line to LF. |
binary
is a macro for -text -diff
, meaning Git will not process this file as text files or generate diffs in git diff
. Git attributes take precedence over the core.autocrlf
config, and will fall back to it when file does not match the wildcards.
Another related config is core.eol
, which only takes effect if a file has the text
attribute. Consider it as the default value for eol
in .gitattributes
, but obviouly it should not be used since it is also a config that needs to be set manually.
More details on Git attributes can be found in the official document.
Renormalize after setting up end-of-line
For existing projects, there is a command that normalizes line endings for all files.
1 | git add --renormalize . |