I am looking again and again at the documentation of .gitattributes but I cannot find a clear answer on what is the differrence between these two:
* text=auto
* text eol=lf
Also is text=auto
intended only for use with *
or it can also be used with specific extensions? In such a case what is the differrence?
*.txt text=auto
*.txt text eol=lf
TL;DR
The
eol=lf
setting overrides anytext
setting, and since you have chosen to apply this to every path, only theeol=lf
setting will matter, if you use that.Full explanation
Let's start with this and work outwards:
Patterns may include extensions. The
text=auto
part is an attribute setting, and the patterns select which attributes to apply to which file(s).How Git reads a
.gitattributes
fileEach line in
.gitattributes
matches, or does not match, some path name such asdir1/dir2/file.ext
orREADME.md
or whatever. As the gitattributes documentation says:Hence,
*
is the pattern. These "patterns" are the same as those in.gitignore
files except that negative patterns are disallowed. Thus, you can use patterns like*.txt
and*.jpg
to match file name extensions, or patterns likedir1/*
to match files within a specific directory (although there is another way to do this: like.gitignore
files, you can have.gitattributes
files per directory, in which case they apply to files in that dierctory and its subdirectories, but not to paths higher in the tree).Now, for
text
vstext=auto
, and foreol=lf
or not, we find the following:(This last one's wording is particularly poor, in my opinion. It really means "of all patterns matching the path, none said anything about this attribute.")
So for
text
, the attribute is set, and fortext=auto
, the attribute is set to a value. The value part in this case isauto
. Since the pattern is*
, it applies to all files.This same logic applies to the
eol=lf
item. If, first, thiseol=lf
occurs in some pattern, and second, that pattern matches the file in question, then theeol
attribute is set to a value, and the value islf
. Since your suggested line was* text eol=lf
, this would makeeol
set to a value, and would maketext
set, but not set to a value.If you write, in a single
.gitattributes
file, the two line sequence:the second line's
text
overrides the first one's, so thattext
is set (but not to a value) andeol
is set to a value, with the value beinglf
. Both lines matched, and the second line overrode the first.If you reverse the two lines:
then again both lines match but now the second line only overrides the
text
setting, so now you havetext
set toauto
andeol
set tolf
.How the
text
attribute applies to filesThe very next section of the gitattributes documentation says:
(which means you have to go chase down the
git config
documentation to find out whatcore.autocrlf
does, if you leavetext
unspecified).You have chosen to either set it for every file, or set it to
auto
for every file. The former means "do conversion for every file" and the latter—theauto
setting—means: Hey, Git, please decide for me whether the file is text or not. If you decide that it is text, do the conversion.How
eol=lf
applies to filesJust below the description for the
text
setting is this description for theeol
setting:So, if you have
eol=lf
set for a path—and with*
as the pattern, it will be set for every path—Git will treat every file as text, and do conversion from CR-LF line endings to LF-only line endings on "checkin" (this is badly phrased, again: the conversion actually occurs during thegit add
step). Git will do nothing during checkout (this too is not perfectly phrased: the conversion—or in this case, non-conversion—happens during extraction from index to work-tree).If you use different patterns you get different results
Note that if you choose a pattern like
*.txt
, then these attributes are set only for paths that match the pattern. For other paths, these attributes remain unset. You should therefore look back at the documentation and see what happens when these attributes are unset.You can, of course, do this:
The first line will explicitly unset
text
on all files, leavingeol
unspecified on all files. The second line then sets to a valueeol=lf
for*.txt
files, overriding the unspecified value. Now Git will apply theeol=lf
rules to all files whose name matches*.txt
, and use the unspecified-eol and unset-text rules for all remaining files.This special
-text
syntax is the stuff I snipped above. Usingtext=false
does not unsettext
: it leavestext
set to the string valuefalse
. This has the same effect as leavingtext
unspecified (not specifically unset). Using-text
gives it the special unset setting.The difference between an unset
text
and an unspecifiedtext
is that whentext
is unspecified, Git could attempt to guess—based on thecore.*
settings likecore.autocrlf
—whether to do conversions. Whentext
is specifically unset, Git will not do any guessing: it will just not do any conversion at all, for that file.