CRLF vs LF
At a glance
| CRLF (\r\n) | LF (\n) | |
|---|---|---|
| Bytes | 0x0D 0x0A (2 bytes) | 0x0A (1 byte) |
| Escape sequence | \r\n | \n |
| Unicode | U+000D followed by U+000A | U+000A |
| Default on | Windows text tooling; DOS lineage | Linux, macOS, BSD; Git object storage |
| Required by | HTTP/1.1 (RFC 9112), SMTP (RFC 5321), MIME headers | POSIX text files; most Unix line-oriented tools |
| Size for 1,000 lines | 2,000 bytes of terminators | 1,000 bytes of terminators |
| Typical failure | Shell script rejected with a trailing ^M in the interpreter path | Older Windows editors render the file as one long line |
Key differences
- CRLF costs one extra byte per line. On a 100,000-line log that is 100 KB of terminators before any content.
- Mixed terminators inside one repository produce whole-file diffs, because every line differs by its invisible trailing byte.
-
Git normalises on the boundary rather than in storage: blobs hold LF, and
.gitattributeswith* text=auto eol=lfsettles the checkout form for every contributor. - Classic Mac OS through version 9 used a bare CR (0x0D), which is why some legacy files carry a third variant that neither modern convention expects.
- Windows Notepad has read and written LF since the Windows 10 October 2018 update, removing the historical reason to keep CRLF in source files.
When to choose which
CRLF (\r\n)
- Writing bytes directly into a protocol that specifies CRLF framing, such as an HTTP/1.1 request line or an SMTP command.
- Producing files consumed by legacy Windows tooling that has not been updated.
- Emitting CSV for spreadsheet software that follows the RFC 4180 recommendation.
LF (\n)
- Source code, configuration and anything stored in Git.
- Shell scripts and any file passed to a Unix interpreter.
- Log files and streaming text, where the extra byte per line compounds.
Frequently asked questions
Is CRLF or LF correct?
Neither is universally correct. LF is the convention for source code and Unix-family systems; CRLF is mandated inside specific protocols such as HTTP/1.1 and SMTP. Correctness is set by the consumer of the file.
What does the ^M at the end of my lines mean?
^M is how Unix tools display a carriage return (0x0D) that is not part of the expected LF terminator. It indicates a CRLF file being read by software that expects LF.
Why does my whole file show as changed in Git?
The line terminator is part of each line. Converting a file from CRLF to LF changes every line by one byte, so a line-based diff reports every line as modified.
Does CRLF make files meaningfully larger?
It adds exactly one byte per line. The effect is negligible for prose and measurable for machine-generated output: a one-million-line dataset carries one extra megabyte of terminators.
Can one file contain both?
Yes. Nothing in a plain text file prevents mixed terminators, which is why editors report a file as having mixed line endings and why normalising on commit is the usual remedy.