Why does .gitattributes not override core.autocrlf

2020-07-18 04:06发布

问题:

While setting up Git for a project, I've noticed that the line-ending normalization works a bit different on Linux and on Windows.

As I understand the Git documentation on this subject, the behavior on Windows is the correct one. Specifically, when a .gitattributes file is present, it should override the core.autocrlf setting.

The following table shows the results of some experimentation I've done. The two left-most columns shows the .gitattributes file and the core.autocrlf setting. The other columns shows the result of the following git commands:

  1. git rm --cached <file> (force next checkout to perform line normalization handling).
  2. git checkout HEAD -- <file> (checkout the file, applying line ending normalization)
  3. git ls-files --eol <file> (check the line endings in the working tree)
+----------------+---------------+-------------+--------------+--------------+--------------------------+--------------------------+
| .gitattributes | core.autocrlf | Linux 2.7.2 | Linux 2.11.0 | Linux 2.16.2 | Windows 2.12.2.windows.2 | Windows 2.16.1.windows.1 |
|                |               |             |              |              |                          |                          |
+----------------+---------------+-------------+--------------+--------------+--------------------------+--------------------------+
| None           | true          | w/crlf      | w/crlf       | w/crlf       | w/crlf                   | w/crlf                   |
|                |               |             |              |              |                          |                          |
+----------------+---------------+-------------+--------------+--------------+--------------------------+--------------------------+
| None           | false         | w/lf        | w/lf         | w/lf         | w/lf                     | w/lf                     |
|                |               |             |              |              |                          |                          |
+----------------+---------------+-------------+--------------+--------------+--------------------------+--------------------------+
| * text=auto    | true          | w/crlf      | w/crlf       | w/crlf       | w/crlf                   | w/crlf                   |
|                |               |             |              |              |                          |                          |
+----------------+---------------+-------------+--------------+--------------+--------------------------+--------------------------+
| * text=auto    | false         | w/lf        | w/lf         | w/lf         | w/crlf                   | w/crlf                   |
|                |               |             |              |              |                          |                          |
+----------------+---------------+-------------+--------------+--------------+--------------------------+--------------------------+
| * text=auto    | true          | w/crlf      | w/crlf       | w/crlf       | w/crlf                   | w/crlf                   |
|   test text    |               |             |              |              |                          |                          |
|                |               |             |              |              |                          |                          |
+----------------+---------------+-------------+--------------+--------------+--------------------------+--------------------------+
| * text=auto    | false         | w/lf        | w/lf         | w/lf         | w/crlf                   | w/crlf                   |
|   test text    |               |             |              |              |                          |                          |
|                |               |             |              |              |                          |                          |
+----------------+---------------+-------------+--------------+--------------+--------------------------+--------------------------+

As you can see, on Linux, it seems that the core.autocrlfsettings has effect, even when a .gitattributesfile is present.

I'd like some help to determine whether this is actually a bug.

回答1:

It seems the misunderstanding comes from interpreting the text attribute as meaning the same thing as the autocrlf config setting.

From the gitattributes docs (https://git-scm.com/docs/gitattributes):

This attribute enables and controls end-of-line normalization. When a text file is normalized, its line endings are converted to LF in the repository. 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

(Emphasis added.)

So if you want to use attributes to control the line ending you get in the work tree, you need to set the eol attribute (not merely the text attributes).

In fact there are a couple attributes and a couple config options involved in how line endings are handled, and there are differences (by design) in the default behavior between Windows and *nix. From the git config docs (https://git-scm.com/docs/git-config):

core.eol

Sets the line ending type to use in the working directory for files that have the text property set when core.autocrlf is false. Alternatives are lf, crlf and native, which uses the platform’s native line ending. The default value is native

So, to answer your question: no, what you've described is not a bug.



回答2:

Note: the .gitattributes documentation has been updated with Git 2.21 (Feb. 2019)

See commit c9446f0, commit 2b68085 (29 Jan 2019) by Jeff King (peff).
Helped-by: Torsten Bögershausen (tboegi).
(Merged by Junio C Hamano -- gitster -- in commit 13e2630, 07 Feb 2019)

doc/gitattributes: clarify "autocrlf overrides eol"

We only override core.eol with core.autocrlf when the latter is set to something besides "false".
Let's make this more clear, and point the reader to the git-config definitions, which discuss this in more detail.

Note that setting core.autocrlf to true or input overrides core.eol (see the definitions of those options in git-config).

And that refers back to Mark Adelsberger's answer regarding core.eol config.
But this has changed with Git 2.21:

docs/config: clarify "text property" in core.eol

`core.eol`:

Sets the line ending type to use in the working directory for files that are
have the text property set when core.autocrlf is false
marked as text (either by having the text attribute set, or by having text=auto and Git auto-detecting the contents as text).

Alternatives are 'lf', 'crlf' and 'native', which uses the platform's native line ending.
The default value is native.
See gitattributes for more information on end-of-line conversion.
Note that this value is ignored if core.autocrlf is set to true or input.