TechEarl

Git: 'LF will be replaced by CRLF' Warning Explained

What 'LF will be replaced by CRLF' means, why it is only a warning, how core.autocrlf works, and how a .gitattributes file settles line endings for a whole team.

Ishan Karunaratne⏱️ 7 min readUpdated
Share thisCopied
Explaining Git's LF will be replaced by CRLF warning and how to fix line endings with core.autocrlf and .gitattributes

LF will be replaced by CRLF is a warning, not an error. Nothing failed, your commit will still happen. Git is telling you that a file uses Unix line endings (LF) in the repository but your core.autocrlf setting will write Windows line endings (CRLF) into your working copy when it next checks the file out. The clean fix is to set the same line-ending policy for everyone with a .gitattributes file.

Here is the full message you are likely staring at:

text
warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it

It almost always shows up on Windows, during git add or git commit, and it can repeat once per file.

What LF and CRLF actually mean

A line ending is the invisible character (or characters) that mark the end of a line in a text file. There are two common conventions:

  • LF (line feed, \n, hex 0A): one character. The Unix, Linux, and macOS standard. Git's own internal storage prefers this.
  • CRLF (carriage return + line feed, \r\n, hex 0D0A): two characters. The Windows standard, inherited from old teleprinters.

The same text file can be byte-for-byte different depending on which convention it uses, even though it looks identical in your editor. That byte difference is the entire source of this warning. When you write code on Windows and your editor saves CRLF, but the repository stores LF, Git has to translate between the two, and it tells you so.

Why this is a warning and not an error

Git is not refusing to do anything. It is doing the conversion you asked it to do (through core.autocrlf) and announcing it. The file gets committed, the repository stays LF, and your working copy stays CRLF. Everything works.

The reason the warning exists at all is that line-ending churn is a real pain on teams: if half the team commits LF and half commits CRLF, you get diffs where every single line looks changed, merge conflicts on whitespace, and broken git blame. The warning is Git nudging you to set a deliberate policy before that mess starts. Line endings are a team concern, not a personal preference, in the same way a clean team Git workflow settles the rest of the shared conventions.

What core.autocrlf is doing

core.autocrlf is the per-machine setting that controls automatic line-ending conversion. It has three values:

ValueOn checkout (repo to working copy)On commit (working copy to repo)Who it is for
trueLF becomes CRLFCRLF becomes LFWindows developers
inputno changeCRLF becomes LFmacOS and Linux developers
falseno changeno changenobody who wants a policy

On Windows the common advice is true: you edit with CRLF locally, Git stores LF in the repo. That is exactly the configuration producing your warning, and it is the correct one. Check what you have:

bash
git config --get core.autocrlf

Set it (the --global flag applies it to your user account, not just this repo):

bash
# Windows
git config --global core.autocrlf true

# macOS / Linux
git config --global core.autocrlf input

core.autocrlf is a personal machine setting, though. It does not travel with the repository, so it cannot guarantee that a teammate has the same value. That is the gap .gitattributes closes.

Make the warning go away with .gitattributes

A .gitattributes file lives in the repo, gets committed, and applies to everyone who clones it, regardless of their core.autocrlf. This is the actual fix for a team. Create the file at the repository root:

bash
echo "* text=auto" > .gitattributes

* text=auto tells Git: treat every file as text and normalize it to LF in the repository, letting it figure out which files are binary on its own. For most projects that single line is enough. If you want to be explicit about a few cases:

text
# Normalize all text files to LF in the repo
* text=auto

# Force LF in the working copy for files that must stay LF
*.sh text eol=lf
*.bash text eol=lf

# Force CRLF in the working copy for Windows-only scripts
*.bat text eol=crlf
*.cmd text eol=crlf

# Treat these as binary, never touch line endings
*.png binary
*.jpg binary
*.pdf binary

eol=lf and eol=crlf override what lands in the working copy for matching files, which matters for shell scripts (a .sh file with CRLF often fails to run) and Windows batch files.

After adding .gitattributes, renormalize the existing files so the repo and your new policy agree:

bash
git add --renormalize .
git commit -m "Add .gitattributes to normalize line endings"

That commit touches the whole repo, so spell out the why in the message: it is the kind of housekeeping change where a clear note pays off later, the same habit that helps you write commits your teammates can read. The renormalize pass may stage files that look unchanged in your editor. That is expected, it is rewriting the stored line endings to match the policy. Commit it once and the recurring warning stops for everyone going forward. If you want to keep mixed line endings from creeping back in, you can automate the policy with a pre-commit hook that flags offending files before they land. This is a sensible thing to set up early, much like the .gitignore file every project should have.

Should I just silence the warning?

You can turn the message off, but I would not lead with that. The warning is harmless, and on a solo repo where you genuinely do not care, suppressing it is fine:

bash
git config --global core.safecrlf false

core.safecrlf controls whether Git warns (or errors) about irreversible line-ending conversions. Setting it to false quiets the warning everywhere. The catch: you have hidden the symptom, not set a policy. The moment a second person clones the repo on a different OS, the line-ending churn is back and now nobody is being warned about it. Prefer the .gitattributes route. Silence the warning only when you have already decided the line endings are correct and you are tired of seeing the note.

reset vs renormalize: a quick clarification

A common reflex when files look "changed" after fixing line endings is to throw the changes away. Do not reach for that here. The renormalize is the work; discarding it leaves you exactly where you started. If you do find yourself wanting to back out a bad attempt, the right tools are covered in discarding local changes in Git, not a blanket reset of the renormalized files.

FAQ

If you are still finding your feet with Git, start at my Git for beginners guide and work outward. Line endings sit right alongside other early setup decisions: what to keep out of the repo with a .gitignore file, how the staging area works when you run git add, and how to set Git up cleanly on a new project. When line-ending churn does cause a tangle, knowing how to resolve merge conflicts is the next skill to have.

Sources

Authoritative references this article was fact-checked against.

TagsLF will be replaced by CRLFGitVersion ControlLine EndingsWindowsgitattributes

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

The Regex (*ACCEPT) Control Verb, Explained

What the PCRE (*ACCEPT) backtracking control verb does, how it forces an immediate successful match, how it behaves inside capturing groups, which engines support it, and where it is genuinely useful.

grep Regex: BRE vs ERE vs PCRE Explained

grep has three regex engines and the default one surprises everyone: in basic regex (BRE) the characters + ? | ( ) { } are literal text until you backslash-escape them. -E switches to extended regex (ERE) where they work bare, and -P unlocks Perl-compatible regex with lookaround and \d. The full BRE vs ERE vs PCRE comparison, the same pattern in all three, and why -P does not exist on macOS.

Git Branching Explained for Beginners

What a Git branch actually is, how HEAD points at your current spot, and the commands to create, switch, list, rename, and delete branches with confidence.