31

Recently I came across the following entry in a .gitattributes file:

"* text=auto !eol"

What does !eol do?

user3226810
  • 319
  • 1
  • 3
  • 3

4 Answers4

25

Git has 2 attributes that deal with end-of-lines:

  1. text

Documentation says:

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

This effectively means that when you commit to the repo, it will convert line-endings to LF

  1. eol

Documentation says:

This attribute sets a specific line-ending style to be used in the working directory. It enables end-of-line normalization without any content checks, effectively setting the text attribute.

So while the text attribute affects how the file will look like IN THE REPO, eol affects how the file looks like in the working directory.

Now, an attribute can have 4 states:

set with no value
example: * text

unset
example: * -text

set with specific value
example: * text=auto

unspecified
example: * !text

So, * text=auto !eol means this:

All files have the attribute text set to auto and the eol attribute unspecified. Reading the documentation we find out that text=auto means that you let Git decide if a file is text and if it is it will normalize it (set line-endings in the repo to LF).

!eol means that the attribute eol is set to unspecified explicitly. In this case it is the same as not specifying it at all, instructing Git to look at the core.autocrlf and core.eol configuration settings to see how to deal with line-endings in the working directory. Note this:

The core.eol configuration variable controls which line endings Git will use for normalized files in your working directory; the default is to use the native line ending for your platform, or CRLF if core.autocrlf is set.

But you would use !eol in a situation like the following:

* text=auto eol=crlf
test.txt !eol

basically overriding the eol attribute from CRLF to unspecified for test.txt. This means that for all files except test.txt, Git will convert line-endings to CRLF on checkout. For test.txt Git will defer to the core.autocrlf and core.eol configuration settings so on any given system the line-ending may be either LF or CRLF.

mkjeldsen
  • 2,053
  • 3
  • 23
  • 28
andrei.serea
  • 950
  • 1
  • 9
  • 15
6
* text=auto !eol

implies:

  • no EOL (end of line) conversion would be performed for binary files.
  • for text files, EOLs are converted to OS-dependent EOL (convert to LF for Unix and CR+LF for Windows) upon checking out the file and replaced with LF while checking in.
devnull
  • 118,548
  • 33
  • 236
  • 227
  • Why **NO** eol conversion? (The `!` is for overriding not for negation.) – michas Jan 23 '14 at 08:31
  • @michas I'm not sure what's your doubt here -- `!eol` in the above applies __only__ to files that are __not__ text files. – devnull Jan 23 '14 at 08:39
  • @devnull How do you figure that `!eol` applies to files that are **not** text? It's on the same line as the `*` wildcard, so it to me means it is removing explicit setting for `eol`, but not sure what the default for `eol` is. This would apply to all files, right? Your answer is confusing. – void.pointer Feb 11 '14 at 17:35
  • @RobertDailey You seem to have ignored the `text=auto` part! – devnull Feb 11 '14 at 17:39
  • @devnull I guess that's where I'm confused. `text=auto` causes the wildcard files to be recognized as text or binary automatically by git. However, I'm not sure how the second attribute (`!eol`) acts on each file. Does `eol`, if unset, also automatically determine if a file is binary or not and appropriately translate line endings? Why not just leave out `!eol` entirely (the effect is the same as not setting it anyway AFAIK) – void.pointer Feb 11 '14 at 17:42
  • 1
    @RobertDailey Think of it this way: `*` says match all files, `text=auto` says handle text files as per OS-dependent EOL, so `!eol` applies to the remaining, i.e. binary. – devnull Feb 11 '14 at 17:50
  • @devnull That makes sense, thank you. So attributes filter files down to the next attribute. My only other question is, if you did not specify `!eol` what would that change? Shouldn't it be the same? i.e. binary files would not be processed? – void.pointer Feb 11 '14 at 18:10
  • @RobertDailey I assume that the behavior should be the same. Haven't verified it, though. – devnull Feb 11 '14 at 18:12
  • This is a correct answer to a broader question, and the discussion is incorrect. The attributes apply to the matched pattern so this unsets (`!`) the `eol` attribute for every file, leaving other mechanisms to determine the result. For files guessed to be binary (`=auto`) those mechanisms ensure no-conversion. – mkjeldsen Feb 06 '22 at 18:37
4

It basically disables eol according to the documentation:

Sometimes you would need to override an setting of an attribute for a path to Unspecified state. This can be done by listing the name of the attribute prefixed with an exclamation point !.

eol does the following:

This attribute sets a specific line-ending style to be used in the working directory. It enables end-of-line normalization without any content checks, effectively setting the text attribute.

Agis
  • 32,639
  • 3
  • 73
  • 81
2

Short version:

If Git decides that the content is text, its line endings are normalized to LF on checkin. Revert any explicit eol setting in some nested .gitattributes file.

See man gitattributes:

   Each line in gitattributes file is of form:

       pattern attr1 attr2 ...

   Sometimes you would need to override an setting of an attribute for a path to
   Unspecified state. This can be done by listing the name of the attribute
   prefixed with an exclamation point !.

   text
       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.

       Set to string value "auto"
           When text is set to "auto", the path is marked for automatic
           end-of-line normalization. If Git decides that the content is text,
           its line endings are normalized to LF on checkin.

   eol
       This attribute sets a specific line-ending style to be used in the working
       directory. It enables end-of-line normalization without any content
       checks, effectively setting the text attribute.
michas
  • 25,361
  • 15
  • 76
  • 121