Quick fix
# One-liner: add .gitattributes at the repo root and renormalize (one-time permanent fix)
printf '* text=auto eol=lf
' > .gitattributes && git add .gitattributes && git add --renormalize . && git commit -m "normalize line endings"
Afterwards git ls-files --eol should show i/lf w/lf.
What you will run into
Changing one line makes git diff mark the entire file as modified (every line red+/green-); git add prints warning: LF will be replaced by CRLF (or the reverse CRLF will be replaced by LF); the same repo checked out on Windows and Linux/WSL looks "the same" but the diff never cleans up;
scripts cloned on Windows fail with ` `-related execution errors. Line-ending policy isn't unified.
Why this happens
Windows text defaults to CRLF (\r\n), Linux/macOS to LF (\n). git's core.autocrlf controls conversion, and what ends up in the repo depends on each person's config at first commit:
| Config | Behavior | Best for |
|---|---|---|
| autocrlf=false | No conversion; CRLF goes into the repo as-is | Old Windows default — the pitfall source for cross-platform repos |
| autocrlf=true | LF on commit, CRLF on checkout | Windows recommended |
| autocrlf=input | LF on commit, no conversion on checkout | Linux recommended |
With everyone configured differently, CRLF/LF gets mixed into the repo — that's the source of "whoever commits, steps on the landmine". warning: LF will be replaced by CRLF itself is harmless, but its appearance means the line-ending policy isn't unified.
Line-ending conversion happens in two directions. core.autocrlf controls "convert CRLF to LF on commit, and convert back on checkout according to the config".
The conversion only rewrites bytes in the text stream; it does not detect file types. That is why binary files can be mangled under autocrlf=true — .gitattributes -text is the escape hatch.
What ends up in the repo depends on each committer's own config: someone with autocrlf=false commits CRLF as-is, someone with autocrlf=true converts to LF — the repo ends up with mixed bytes, and git diff shows whole-line changes.
Deterministic takeaway: the LF will be replaced by CRLF warning means conversion happened on checkout — the config is in effect but the policy is not unified.
Cross-platform repos should write the policy into the repo itself via .gitattributes (* text=auto plus explicit declarations like *.sh text eol=lf), not rely on per-machine local config — config is per-machine, attributes travel with the repo.
Step by step
1. When the symptom is harmless (just a warning, diff is clean) — Required
Make the whole team's core.autocrlf consistent (Windows true, Linux/mac input); the warning disappears.
2. Diff all-red / already mixed into the repo (recommended, permanent) — Required
Add .gitattributes at the repo root:
* text=auto eol=lf
Then renormalize (converting every CRLF already in history to LF):
git add .gitattributes
git add --renormalize .
git commit -m "normalize line endings"
3. Manage only specific types — Required
Write *.sh text eol=lf, *.bat text eol=crlf etc. in .gitattributes, leave the rest alone.
4. Avoid repeating it — Required
For new repos, commit .gitattributes (* text=auto) at the root before adding content; don't use autocrlf=false as the default for cross-platform repos (that stores CRLF into the repo).
How to confirm it works
Repo format is unified (measured output shape):
git ls-files --eol → all i/lf w/lf, no warnings
git diff → only real changes shown (adding 1 line reports 1 insertion, measured)Other environments
| Environment | Notes |
|---|---|
| Windows | autocrlf=true (LF on commit, CRLF on checkout) |
| Linux/mac | autocrlf=input |
| Already mixed into repo | .gitattributes + git add --renormalize . (measured fix) |
| Specific files | *.sh text eol=lf, *.bat text eol=crlf |
| New repos | Commit .gitattributes before adding content |
Symptom
- You change one line, but
git diffmarks the entire file as modified (every line red+/green-); git addprintswarning: in the working copy of 'xxx', LF will be replaced by CRLF the next time Git touches it(or the reverseCRLF will be replaced by LF);- The same repo checked out on Windows and Linux/WSL looks identical but diff never gets clean;
- Scripts (.sh/.py) cloned on Windows fail with \r-related execution errors (CRLF leaked into the script).
Key traits: plain-text files; the message mentions line endings; repos collaborated on across Windows/Linux hit it most.
Cause
Windows text defaults to CRLF (\r\n), Linux/macOS to LF (\n). core.autocrlf controls conversion, and what actually gets stored depends on each committer's config:
autocrlf=false(old git default on Windows, many outdated tutorials): no conversion at commit — CRLF gets stored directly in the repo, and any LF working copy diffs as all-lines-changed;autocrlf=true(recommended on Windows): commit converts to LF, checkout to CRLF;autocrlf=input(recommended on Linux): commit converts to LF, checkout stays LF.
When teammates use different settings (Windows false + Linux input/false), CRLF and LF end up mixed in the repo — whoever commits next hits the mess. The warning itself is harmless (git is just telling you it will convert), but its appearance means the line-ending policy isn't unified.
Solution
- Warning only, diff clean: unify
core.autocrlfacross the team (Windowstrue, Linux/macinput); the warning disappears. - Diff all-red / already mixed (recommended, one-time fix): add a root
.gitattributes:
* text=auto eol=lf
then renormalize (convert all stored CRLF to LF):
git add .gitattributes
git add --renormalize .
git commit -m "normalize line endings"
Afterwards git ls-files --eol should show i/lf w/lf (both index and worktree LF).
- Per-type control:
.gitattributesentries like*.sh text eol=lf,*.bat text eol=crlf, leave the rest untouched. - Prevention: commit
.gitattributes(* text=auto) at repo root BEFORE adding content; don't useautocrlf=falseas the default for cross-platform repos (it stores CRLF in the repo).
Verification Evidence
- Local repro (2026-08-29, WSL Ubuntu, git 2.53.0):
- Repro 1 (diff all-red): committed a CRLF file with
autocrlf=false(git ls-files --eolshowsi/crlf w/crlf) → changed worktree to LF →git diffshows 2 lines as 3 deletions + 2 additions (every line changed); - Repro 2 (warning forward): with
autocrlf=true, adding an LF file →warning: in the working copy of 'lf.txt', LF will be replaced by CRLF the next time Git touches it; - Repro 3 (warning reverse): with
autocrlf=input, adding a CRLF file →warning: ... CRLF will be replaced by LF ...; - Fix: root
.gitattributes(* text=auto eol=lf) +git add --renormalize .→ all stored files becomei/lf w/lf, no warnings; - After fix, diff shows only the real change (1 insertion for 1 added line).
Evidence details kept locally (2026-08-29)
Applicable tools (1)
This problem is linked from the tool pages below — reachable from either side.
gitSource & evidence
← Coding Agents & Terminal domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk