Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.gitattributes: does text=auto still uses core.autocrlf to detect EOL

Tags:

git

With a .gitattributes entry

 * text=auto

what line separators are used when checking out the text files? The documentation states:

Set to string value "auto"

When text is set to "auto", the path is marked for automatic end-of-line conversion. If Git decides that the content is text, its line endings are converted to LF on checkin. When the file has been committed with CRLF, no conversion is done.

Unspecified

If the text attribute is unspecified, Git uses the core.autocrlf configuration variable to determine if the file should be converted.

This sounds to me that in case of text=auto core.autocrlf does not matter. Am I right?

like image 506
Thomas S. Avatar asked Jan 30 '23 22:01

Thomas S.


1 Answers

This sounds to me that in case of text=auto [in .gitattributes, having] core.autocrlf [in the configuration] does not matter. Am I right?

Mostly. The git config documentation now says, for core.autocrlf:

Setting this variable to "true" is the same as setting the text attribute to "auto" on all files and core.eol to "crlf". ... This variable can be set to input, in which case no output conversion is performed.

Confusingly, just a few lines earlier, the git config documetnation says, for core.eol itself:

Sets the line ending type to use in the working directory for files that have the text property set when core.autocrlf is false [and I tell you nothing about when it set to true or to input]... See gitattributes(5) for more information on end-of-line conversion.

(boldface and bracketed text mine). And yet, the description of core.autocrlf talks about effectively setting core.eol, so what does happen when core.autocrlf is either true or input, and core.eol is set to crlf?

If we turn to the gitattributes documentation, we find this phrase hidden away:

To control what line ending style is used in the working directory, use the eol attribute for a single file and the core.eol configuration variable for all text files. Note that core.autocrlf overrides core.eol

So, if you don't set core.autocrlf, this doesn't override core.eol either. This means that whatever you choose for core.eol applies as a default. But if you do set core.autocrlf, whatever you choose for a core.eol setting gets ignored!


The actual source code inside Git is terribly twisty (and has undergone numerous changes over the years). There are a few things that one can say that are true across all Git variants, though:

  1. Conversions normally1 occur in just two places: when a file is copied from the index to the work-tree (the "output" phase), or when a file is copied from the work-tree to the index (the "input" phase). The output side copies happen during git checkout and git checkout-index, both of which copy files from the index to the work-tree. The input side copies happen during git add, which copies files from the work-tree to the index.

  2. A file considered to be "binary" does not get modified. A file considered to be "text" is a candidate for modification.

So, * text=auto means that all files become candidates for modification, and core.autocrlf has the same effect. But exactly what modification is applied? That part is tricky. Assuming the above quotes from the two different configuration documentation sections are correct for all versions of Git:

  • If, for any particular path, you have a .gitattributes setting with a specific eol=, the core.eol setting does not matter. But this is independent of whether you have a .gitattributes setting for text=.
  • Therefore, wherever you forgot to also have a specific eol= settting, your effective core.eol setting controls what those conversions are.

Hence, since core.autocrlf can change the effective core.eol setting, and you can neglect to set a specific setting for some text file, having core.autocrlf set can be like changing your core.eol setting to crlf, even if you do already have text=auto set for all files. (What precisely happens if you set core.autocrlf to input would require careful testing.)


1The word normally is here because this talks about where files get converted on the way in and out of Git. For some operations, though, such as git diff against a work-tree, or git merge with "normalization" enabled, Git must do a "virtual check-in" or "virtual check-in and check-out", in which case Git does some extra converting. This is, unfortunately, why the actual code inside Git is so terribly twisty.

like image 122
torek Avatar answered Feb 05 '23 15:02

torek