How line ending conversions work with git core.autocrlf between different operating systems How line ending conversions work with git core.autocrlf between different operating systems git git

How line ending conversions work with git core.autocrlf between different operating systems


The best explanation of how core.autocrlf works is found on the gitattributes man page, in the text attribute section.

This is how core.autocrlf appears to work currently (or at least since v1.7.2 from what I am aware):

  • core.autocrlf = true
  1. Text files checked-out from the repository that have only LF characters are normalized to CRLF in your working tree; files that contain CRLF in the repository will not be touched
  2. Text files that have only LF characters in the repository, are normalized from CRLF to LF when committed back to the repository. Files that contain CRLF in the repository will be committed untouched.
  • core.autocrlf = input
  1. Text files checked-out from the repository will keep original EOL characters in your working tree.
  2. Text files in your working tree with CRLF characters are normalized to LF when committed back to the repository.
  • core.autocrlf = false
  1. core.eol dictates EOL characters in the text files of your working tree.
  2. core.eol = native by default, which means Windows EOLs are CRLF and *nix EOLs are LF in working trees.
  3. Repository gitattributes settings determines EOL character normalization for commits to the repository (default is normalization to LF characters).

I've only just recently researched this issue and I also find the situation to be very convoluted. The core.eol setting definitely helped clarify how EOL characters are handled by git.


The issue of EOLs in mixed-platform projects has been making my life miserable for a long time. The problems usually arise when there are already files with different and mixed EOLs already in the repo. This means that:

  1. The repo may have different files with different EOLs
  2. Some files in the repo may have mixed EOL, e.g. a combination of CRLF and LF in the same file.

How this happens is not the issue here, but it does happen.

I ran some conversion tests on Windows for the various modes and their combinations.
Here is what I got, in a slightly modified table:

                 | Resulting conversion when       | Resulting conversion when                  | committing files with various   | checking out FROM repo -                  | EOLs INTO repo and              | with mixed files in it and                 |  core.autocrlf value:           | core.autocrlf value:           --------------------------------------------------------------------------------File             | true       | input      | false | true       | input | false--------------------------------------------------------------------------------Windows-CRLF     | CRLF -> LF | CRLF -> LF | as-is | as-is      | as-is | as-isUnix -LF         | as-is      | as-is      | as-is | LF -> CRLF | as-is | as-isMac  -CR         | as-is      | as-is      | as-is | as-is      | as-is | as-isMixed-CRLF+LF    | as-is      | as-is      | as-is | as-is      | as-is | as-isMixed-CRLF+LF+CR | as-is      | as-is      | as-is | as-is      | as-is | as-is

As you can see, there are 2 cases when conversion happens on commit (3 left columns). In the rest of the cases the files are committed as-is.

Upon checkout (3 right columns), there is only 1 case where conversion happens when:

  1. core.autocrlf is true and
  2. the file in the repo has the LF EOL.

Most surprising for me, and I suspect, the cause of many EOL problems is that there is no configuration in which mixed EOL like CRLF+LF get normalized.

Note also that "old" Mac EOLs of CR only also never get converted.
This means that if a badly written EOL conversion script tries to convert a mixed ending file with CRLFs+LFs, by just converting LFs to CRLFs, then it will leave the file in a mixed mode with "lonely" CRs wherever a CRLF was converted to CRCRLF.
Git will then not convert anything, even in true mode, and EOL havoc continues. This actually happened to me and messed up my files really badly, since some editors and compilers (e.g. VS2010) don't like Mac EOLs.

I guess the only way to really handle these problems is to occasionally normalize the whole repo by checking out all the files in input or false mode, running a proper normalization and re-committing the changed files (if any). On Windows, presumably resume working with core.autocrlf true.


core.autocrlf value does not depend on OS type but on Windows default value is true and for Linux - input. I explored 3 possible values for commit and checkout cases and this is the resulting table:

╔═══════════════╦══════════════╦══════════════╦══════════════╗║ core.autocrlf ║     false    ║     input    ║     true     ║╠═══════════════╬══════════════╬══════════════╬══════════════╣║               ║ LF   => LF   ║ LF   => LF   ║ LF   => LF   ║║ git commit    ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║║               ║ CRLF => CRLF ║ CRLF => LF   ║ CRLF => LF   ║╠═══════════════╬══════════════╬══════════════╬══════════════╣║               ║ LF   => LF   ║ LF   => LF   ║ LF   => CRLF ║║ git checkout  ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║╚═══════════════╩══════════════╩══════════════╩══════════════╝