Git warning LF will be replaced by CRLF: use one line ending in a repo shared by Windows and Mac

Translated from the original Traditional Chinese version.

Summary

Windows and Mac use different line endings in text files. Git for Windows converts them when it checks out files, which is why git add prints the warning LF will be replaced by CRLF. Add one config file to the repo that sets the line ending, and the files committed to the repo and checked out on every computer use the same one, whatever each person’s Git settings are. A Mac then no longer shows a diff that rewrites every line.

Table of contents

Every line in a text file ends with a line ending character. Windows usually uses CRLF (\r\n), while Mac and Linux use LF (\n). Git for Windows converts LF to CRLF by default when it checks out files. When you run git add on an LF file on Windows, you see the warning LF will be replaced by CRLF the next time Git touches it.

If you develop only on Windows, you can ignore this warning. In a repo you share with a Mac, the problem starts when someone turns off the automatic conversion and commits a file with CRLF. After an editor on the Mac saves the file with LF, every line in the file shows as changed. Add a .gitattributes file to the repo that sets the line ending. Then the files committed to the repo and checked out on every computer use the same line ending, whatever each person’s Git settings are.

I tested with Git 2.55.0 (Git for Windows) on Windows 11 and Git 2.54.0 (Apple Git) on macOS.

What the warning means

The Git for Windows installer enables automatic conversion by default and writes core.autocrlf=true to the system config file. Run git config --show-origin core.autocrlf to see the value and the config file it comes from. With this setting, git add on an LF file prints the warning:

Windows PowerShell shows core.autocrlf set to true from C:/Program Files/Git/etc/gitconfig, the LF will be replaced by CRLF warning when running git add app.js, and git ls-files –eol showing i/lf w/lf

git ls-files --eol lists the line ending of each file in the repo and on your computer. To diagnose a line ending problem, look at these three fields:

Field Meaning Example
i/ Line ending committed to the repo (the index) i/lf means the repo has LF
w/ Line ending of the file on your computer (the working tree) w/crlf means your computer has CRLF
attr/ What .gitattributes sets for the file Empty when nothing is set

In the screenshot, i/lf means the repo still stores LF. The warning only says that the next checkout will change the file to CRLF. I deleted the file and checked it out again with git checkout, and the file on my computer became w/crlf.

The diff that line ending differences cause

Git on a Mac does not convert line endings by default. On the Mac, I simulated a Windows teammate with automatic conversion turned off. I committed a two-line file with CRLF, then saved it with LF. Git treated both lines as changed:

Step Command Result
After committing with CRLF git ls-files --eol i/crlf w/crlf, so the repo stores CRLF
After the editor saves with LF git diff --stat app.js | 4 ++--, two lines deleted and two added

Run git diff | cat -v and each deleted line ends with an extra ^M. That is the \r in CRLF, and the text itself did not change:

1-const a = 1;^M
2-const b = 2;^M
3+const a = 1;
4+const b = 2;

With many files, the real changes get buried in these differences.

Set one line ending with .gitattributes

A .gitattributes setting takes priority over core.autocrlf on each person’s computer. According to the Git documentation, Git applies core.autocrlf only to files whose text attribute is not set. So you do not need to ask everyone to change their own Git settings. Normalizing line endings changes many files, so commit your current changes first. Then follow these four steps:

  1. Create .gitattributes in the repo root with the line below. text=auto lets Git detect which files are text, and eol=lf makes text files use LF when checked out on both Windows and Mac:

    1* text=auto eol=lf
    
  2. Add .gitattributes to the repo, run git add --renormalize . so the files you already committed follow the new rule, and then commit:

    1git add .gitattributes
    2git add --renormalize .
    3git commit -m "Normalize line endings to LF"
    
  3. Files that already exist on your computer change to LF only after you check them out again. The two commands below regenerate every file from the repo. git reset --hard discards uncommitted changes, so run it only after you commit:

    1git rm -rq --cached .
    2git reset -q --hard
    
  4. Everyone else who already cloned the repo runs the two commands from step 3 after git pull.

I followed these steps on Windows. After the commit (step 2), git ls-files --eol still showed w/crlf. After step 3, .gitattributes and app.js became i/lf w/lf, and the attr/ field showed the new setting. The CRLF will be replaced by LF message from git add .gitattributes appears because .gitattributes created in Windows PowerShell itself uses CRLF. Git converts it to LF on commit, so you can ignore the message:

After git add .gitattributes, git add –renormalize ., and git commit, git ls-files –eol shows w/crlf. After git rm –cached and git reset –hard, it shows i/lf w/lf attr/text=auto eol=lf

I also simulated a teammate with two clones. After the teammate ran git pull, app.js was still w/crlf, and it became w/lf only after step 3. After that, adding a new LF file on Windows and running git add no longer printed the LF will be replaced by CRLF warning. On the Mac with the same config, a file that I had committed with CRLF became i/lf after renormalizing, and the file on the computer was LF after a fresh checkout.

The status bar at the bottom right of the VS Code window shows the line ending of the current file, so you can use it to confirm the result. The same app.js showed CRLF when checked out before I added .gitattributes, and LF when checked out again afterward:

The line ending indicator in the VS Code status bar, CRLF before the setting and LF after it

Summary

In a repo shared by Windows and Mac, add a .gitattributes file at the root that makes every text file use LF, then normalize the committed files and the files on each computer once. In my tests on Windows and Mac, both the repo and the files on the computer used LF after the change, and git add on Windows no longer printed the LF will be replaced by CRLF warning.

Ted Liou

Ted Liou

Software engineer writing about Unity and AI development. Available for consulting.

Comments