By admin , 29 April 2026

The line-ending problem

Windows uses CRLF (\r\n), Linux and macOS use LF (\n). When developers on different platforms commit to the same repository, files flip back and forth and diffs become unreadable. .gitattributes is the cure.

The simple, robust setup

# .gitattributes
* text=auto eol=lf

*.{cmd,bat,ps1} text eol=crlf

*.png binary
*.jpg binary
*.pdf binary
*.zip binary

* text=auto eol=lf tells Git: "auto-detect text files, store them with LF endings, and convert to LF on checkout." Windows-only scripts force CRLF; binaries are marked so Git does not touch them.

How text=auto works

On commit, Git looks at file contents. Apparent text files have their working-tree line endings normalised to LF in the repository. Apparent binaries are stored verbatim. On checkout, the configured core.autocrlf may convert back to CRLF for Windows users, but with eol=lf in .gitattributes, you override the user setting and get LF everywhere.

Renormalising existing repos

If you adopt .gitattributes on a repo with mixed endings, you must renormalise:

# Backup first!
git add --renormalize .
git commit -m "Normalize line endings"

This rewrites the index according to the new attributes. Diff afterwards to verify only line endings changed.

core.autocrlf versus .gitattributes

Two ways to manage line endings:

  • core.autocrlf - per-user config; differs between developers.
  • .gitattributes - committed to the repo; the same for everyone.

.gitattributes wins. Per-user config invites inconsistency.

Marking binaries

Even if text=auto guesses correctly most of the time, mark binaries explicitly to prevent surprises:

*.png binary
*.jpg binary
*.gif binary
*.ico binary
*.pdf binary
*.zip binary
*.tar binary
*.gz binary
*.dll binary
*.exe binary

binary is shorthand for -text -diff: do not normalise, do not diff.

Per-file overrides

Makefile     text eol=lf
*.sh         text eol=lf
*.bat        text eol=crlf
*.ps1        text eol=crlf
*.csv        text     # treat CSVs as text but allow either ending

Diff drivers and merge drivers

Beyond line endings, .gitattributes can configure diff and merge for specific file types:

*.docx diff=docx
*.pdf diff=pdf
composer.lock merge=ours

This lets you teach Git to compare Word documents via Pandoc or skip merging on lockfiles.

Verifying

git check-attr -a path/to/file
git ls-files --eol

--eol prints the working tree and index line-ending state per file. A clean repo shows consistent values.

The recommendation

Add a .gitattributes file with * text=auto eol=lf and binary markers to every repo on day one. Renormalise once. After that, line-ending churn becomes a non-issue.