Search code examples
gitnewlineeolgitattributes

Git attributes: `-text` vs `eol=lf`


I want to configure a git repository in a way that all checkouts use LF as line endings, even on windows if core.autocrlf is enabled. I got the following ideas from the documentation:

  • text means: the file should undergo line-ending conversion
  • text=auto means: the file should undergo line-ending conversion, if heuristics determine that this is a text file.
  • -text means: the file should never undergo line-ending conversion.

I intentionally did not specify yet, what "line-ending conversion" means in detail, because that depends on global configuration and the eol attribute:

  • eol=crlf means: line-ending conversion should translate between LF in the repository and CR/LF in the working copy.
  • eol=lf means: line-ending conversion should translate between LF in the repository and LF in the working copy, i.e. it is an identity transformation
  • eol unspecified means: use system-dependent default (depends on global git configuration, working copy configuration and/or the native line ending convention of the host OS)

It looks like there is no difference between using * -text, * text=auto eol=lf or even * text eol=lf, because it shouldn't matter whether the line-ending conversion is disabled, or it is enabled but doesn't do anything. Am I missing advantages or disadvantages of either configuration?


Solution

  • There is absolutely a difference between these options, but it can be subtle.

    First, text=auto usually does a good job, but not always, because it uses a heuristic and only looks at the beginning of the file. It just so happens that many PDF files start off with a bunch of text and then contain lots of binary data, so they tend to be frequently misdetected. In most cases, you want to avoid checking in generated files like PDFs in favour of their source files, but it's an example of a case where specifying -text or text explicitly is useful.

    Settting text eol=lf says that when you use git add, you want the file to be converted to LF in the repository, and when you check it out, you want LF in the working tree. However, if someone on Windows misconfigured their editor and wrote the file to disk with CRLF, Git will still convert that to LF in the repository, and you'll get an error like this: “warning: in the working copy of 'abc.foo', CRLF will be replaced by LF the next time Git touches it”. Thus, it is an identity transformation when checking out, but not when adding to the repository.

    It should be noted that users can also override the .gitattributes file with .git/info/attributes. If the user sets eol=crlf there, then the file will still be checked out with CRLF line endings.

    Setting -text disables all line ending conversion. The implicit context is that this is a binary file, such as an image, and no line ending conversion is done. If there is a CR or LF (or any other byte sequence) in the file, it won't be changed in any way. This is an identity transformation.