What do Git's core.autocrlf values true, input, and false each do?
answer
- Two conversion points: check-in and checkout
- One value converts both ways
- One value converts on the way in only
- The default converts nothing
- Attributes override this config
basics
~20 sIn Git, core.autocrlf=true converts CRLF to LF on commit and back to CRLF on checkout; input converts to LF on commit but never converts on checkout; false, the default, stores and checks out the bytes unchanged.
solid answer
~40 s`core.autocrlf` controls Git's automatic line-ending conversion for files it treats as text. With `true` — the usual Windows setting — Git converts CRLF to LF when content enters the object database and LF back to CRLF on checkout, so the repository stays LF while the working tree is native. With `input`, Git still converts CRLF to LF on the way in but performs no conversion on checkout; that is the usual macOS and Linux setting, and it catches a file that somehow arrived with CRLF. With `false`, the default, Git does nothing: whatever bytes you stage are the bytes it stores and returns. Two caveats matter: it is a per-machine config, so it does not travel with a clone, and any `text` attribute in `.gitattributes` overrides it for the paths it covers.
code
bash · 8 lines# Unix-side: normalise on the way in, never on checkout
git config --global core.autocrlf input
# Where is the value actually coming from?
git config --show-origin core.autocrlf
# Warn instead of silently losing mixed endings
git config --global core.safecrlf warngo deeper
Memorise the three values and which direction each converts, and remember the default is no conversion at all.
Explain both conversion points precisely, say how Git decides a file is text, and state that a text attribute overrides this setting for the paths it matches.
Demonstrate diagnosis: trace the effective value with --show-origin, recognise the safecrlf warning as a mixed-endings signal, and explain why you would move the policy into the repository instead.
Own the argument that per-machine configuration cannot be a team policy — new clones, contractors, containers and CI all default differently, so the rule must be versioned with the code.
## The two conversion points Git has exactly two places where line-ending conversion can happen: **check-in**, when working-tree content is turned into a blob (during `git add` or `git commit -a`), and **check-out**, when a blob is written into the working tree. Everything in this topic is a rule about those two moments. `core.autocrlf` is one way to state the rule; a `text` attribute in `.gitattributes` is the other. ## The three values **`core.autocrlf = true`** — convert both ways. On check-in, CRLF sequences in files Git considers text are collapsed to LF, so the object database stores LF. On checkout, LF is expanded to CRLF, so the working tree looks native to Windows tools. This is the setting Git for Windows installers usually offer by default. **`core.autocrlf = input`** — convert on the way in only. CRLF becomes LF when content is staged; checkout writes exactly what is stored, which is LF. This suits Unix-like machines: it costs nothing on checkout and still stops a CRLF file from sneaking into history if a file arrives from a Windows tool or an unzip. **`core.autocrlf = false`** — the default. No conversion at either point. What you stage is what is stored; what is stored is what appears on disk. Fine when everyone already uses LF, and the correct choice when you have expressed the policy in `.gitattributes` and want the attributes to be the only rule. ## What counts as "text" Conversion applies only to files Git treats as text. When `core.autocrlf` is enabled and a path has no `text` attribute, Git runs its own content heuristic: content containing NUL bytes early in the file is treated as binary and left alone. That heuristic is good but not authoritative, which is one reason explicit attributes are preferred: a file it guesses wrong about is either corrupted (a binary silently rewritten) or left churning. ## Precedence against attributes When a path is covered by a `text` attribute in `.gitattributes`, that attribute decides. `text` marks the path for normalisation to LF in the repository; `-text` (unset) disables all conversion for that path regardless of `core.autocrlf`; `eol=lf` or `eol=crlf` pins the working-tree ending; `binary` is a macro that unsets `text` along with `diff` and `merge`. `core.eol` selects the working-tree ending for paths that are marked `text` but have no explicit `eol` — its values are `lf`, `crlf` and `native` (the default), and `core.autocrlf=true` effectively overrides it to CRLF. In short: attributes beat config, and config beats nothing. ## The safety valve `core.safecrlf` guards against conversions that would not round-trip. Set to `warn`, Git prints a warning when a check-in conversion would not reproduce the original file byte-for-byte — typically because the file has *mixed* endings, so collapsing CRLF to LF loses information about which lines were which. Set to `true`, Git refuses the operation instead. The frequently-seen "CRLF will be replaced by LF" message comes from this machinery, and it is informational, not an error. ## Why it is not the real answer `core.autocrlf` lives in a user's `~/.gitconfig` or the repository's `.git/config`. Neither travels with a clone. That means the repository's line-ending policy depends on whether every current and future contributor, plus every CI job and container image, happened to set the same value — and on nobody setting `true` on a Linux box, which would expand endings to CRLF and hand you a repository full of carriage returns. The robust configuration is `* text=auto` in a committed `.gitattributes` (with per-path `eol=lf` for shell scripts and `eol=crlf` or `-text` where a tool demands it), and leaving `core.autocrlf` alone. Understanding the three values still matters, because you will inherit repositories configured the old way, and because diagnosing someone's churn usually starts with asking what their `core.autocrlf` is set to — `git config --show-origin core.autocrlf` answers that in one line. ## Interview framing State the three behaviours precisely in terms of check-in and check-out, name `input` as the Unix-side setting, note that the heuristic decides what is text, and finish by saying the config does not travel with the clone — which is why the attributes file exists.
- What does the message "CRLF will be replaced by LF" actually mean?It comes from `core.safecrlf` and reports that the check-in conversion will not round-trip byte-for-byte — usually because the file has mixed endings. At the `warn` level it is informational and the commit proceeds; set to `true` Git refuses the operation instead.
- What happens if someone on Linux sets core.autocrlf to true?Their checkouts expand LF to CRLF, so every text file on disk gets carriage returns. Build scripts and interpreters that dislike `\r` start failing, and any tool that rewrites a file without re-adding the CRLF produces whole-file churn. `input` is the correct Unix-side value.
- Does core.autocrlf touch binary files?Not intentionally. Conversion applies only to content Git's heuristic judges to be text, which keys on NUL bytes near the start of the file. The heuristic can be wrong, which is why safety-critical paths should carry an explicit `-text` or `binary` attribute instead of relying on detection.
saying these in an interview costs you the question
- Says input converts on checkout as well
- Thinks core.autocrlf is stored in the repository and shared
- Believes true is the default everywhere
- Claims it rewrites binary files unconditionally
- Cannot say which wins between attributes and this config