Using .gitattributes to manage line endings during checkout

Viewed 252

Using SmartGit version 21.2.1 (git version 2.30.2.windows.1). I have an existing git repo in which some files use CRLF for line endings and some use LF. I found https://git-scm.com/docs/gitattributes and am experimenting with what happens during checkout. The doc seems to say the following .gitattributes should normalize all files to use LF endings during checkin, and during checkout give me control over how they look:

* text=auto eol=crlf
*.py eol=lf

Does Line 1 mean:

By default, evaluate all files to determine if they are text files. If they aren't, leave them alone. If they are text files then on checkout convert line endings to CRLF and on checkin convert to LF.

Does Line 2 override Line 1 for Python files this way:

Treat Python files as text files and on checkout and checkin convert line endings to LF.

I tried this experiment and got unexpected results. Initial conditions: global core.autocrlf=false, no .gitattributes file in the repo.

  1. Create a "legacy" repo with these files (names indicate line endings at checkin time): CRLF.txt, LF.txt, CRLF.py, LF.py
  2. Check out a different branch and then go back to the original branch; confirm checkout did not change any file's line endings.
  3. Check in a .gitattributes file containing the above 2 lines
  4. Check out a different branch and then go back to the original branch.

After step 4 I was expecting to find these line endings:

CRLF in CRLF.txt
CRLF in LF.txt
LF in CRLF.py
LF in LF.py

(I expected Line 1 to handle the .txt files and Line 2 to handle the .py files)

But this is what I actually got:

CRLF in CRLF.txt
CRLF in LF.txt
CRLF in CRLF.py
LF in LF.py

TXT files look good, but why didn't git convert CRLF.py to end in LF after the checkout?

1 Answers

It appears I misinterpreted the git docs. The eol attribute only converts on checkout when it is set to:

eol=crlf

Whereas this value acts only as a "conversion blocker":

eol=lf

so you get whatever was in the index. In both cases, though, eol normalizes files to LF on checkin, but I wasn't modifying/checking in any of the files during my experiment.

I figured this out because when I added the text attribute to Line 2:

*.py text eol=lf

because then I got prompted to check CRLF.py in (even though I hadn't changed it), thus it got normalized to LF in the index. This line in the docs make it sound like adding the text attribute to Line 2 should be unnecessary:

eol: Enables end-of-line conversion without any content checks, effectively setting the text attribute.

But seemingly without the text attribute you don't get prompted to checkin/normalize the .py files and so this wouldn't happen until the next time you manually change the files for some other reason and check it in.

Related