In Git, what does marking a path binary in .gitattributes actually change?
answer
- It is a macro, not a primitive
- Expands into three separate unsets
- One of them decides display, one merging
- Git also guesses this from content
basics
~10 sThe binary attribute is a built-in macro expanding to -diff -merge -text. Git then reports the file as differing rather than showing a textual diff, refuses to content-merge it, and applies no end-of-line conversion.
solid answer
~50 s`binary` is not a special flag but a **macro** that Git expands to `-diff -merge -text`. Unsetting `diff` means `git diff` and `git show` print `Binary files a/x and b/x differ` instead of attempting a line diff. Unsetting `merge` means a three-way merge makes no attempt to combine the sides: Git takes the current branch's version as the tentative result and declares a conflict, so a human resolves it by choosing a whole file, typically with `git checkout --ours` or `--theirs` followed by `git add`. Unsetting `text` disables end-of-line conversion so bytes round-trip unchanged. Git already guesses binariness from content, so the value of the attribute is determinism and reach: it covers files that look textual but must never be line-merged, such as minified bundles, generated schemas or UTF-16 documents, and it makes the intent explicit and shared rather than dependent on a heuristic.
code
gitattributes · 4 lines*.png binary
*.pdf binary
package-lock.json -diff
db/schema.sql -mergego deeper
Know that the attribute tells Git not to try to diff or merge a file's contents, and that it is written next to a pattern in the attributes file, for example for image extensions.
State the expansion into three unset attributes and what each one changes: no textual diff, no content merge with a declared conflict, and no end-of-line conversion. Mention that Git also guesses binariness from content.
Show judgment about the subsets: unset diff alone for generated text that should still merge, unset merge alone for files where interleaving is unsafe, and explain the whole-file resolution path a conflict then requires.
Own the policy for generated and binary artifacts across repositories: what gets committed at all, which attributes make review and merges predictable for everyone, and why an explicit committed declaration beats relying on a per-blob heuristic.
## A macro, not a mode Git ships one built-in macro attribute, `binary`, defined as `-diff -merge -text`. Writing `*.pdf binary` in `.gitattributes` is exactly equivalent to writing the three unset attributes yourself. Knowing that expansion is the whole question, because each of the three does something separate and you sometimes want only one of them. ## Unsetting diff With `diff` unset, Git does not produce a textual diff for the path. `git diff`, `git show` and `git log -p` print a one-line notice that the files differ. This keeps review output readable when the content is machine-generated or genuinely non-textual, and it avoids the pathological case of a diff that is larger than the file. It is the attribute you want on its own when a file is textual but not worth reviewing line by line, such as a lockfile or a bundled artifact. `path -diff` gives you that without touching merge behaviour. ## Unsetting merge With `merge` unset, Git does not attempt a content-level three-way merge. When the two sides both changed the file, Git takes the version from the current branch as the tentative result and declares a conflict. Nothing is spliced, no conflict markers are inserted into the bytes, and the resolution is necessarily a whole-file choice: inspect both sides, pick one with `git checkout --ours <path>` or `git checkout --theirs <path>`, or regenerate the file, then `git add` it. This is the behaviour you want for anything where interleaving two edits produces a corrupt file: images, archives, compiled assets, and also plenty of text formats where a merged result would be syntactically valid but semantically wrong. ## Unsetting text With `text` unset, Git performs no end-of-line conversion in either direction, so the bytes stored and the bytes checked out are identical. For real binary content this is not optional; a conversion would corrupt the file. ## Why declare it when Git already guesses Git applies a content heuristic: if a blob contains a NUL byte near the start it is treated as binary for diff purposes. The heuristic is good but it is a guess made per blob, and it does not help for content that is textual by encoding yet must not be merged. Declaring the attribute gives you three things the heuristic cannot: it is explicit, so a reader of the repository sees the intent; it is committed, so every contributor and every automated checkout behaves the same way; and it covers merge and eol decisions, not only display. ## Choosing the right subset - Genuinely binary content: `binary` is right, all three unsets apply. - Generated text you do not want in review but do want merged as text: `-diff` alone. - Text you want reviewable but never auto-merged: `-merge` alone. - Reaching for `binary` on ordinary source files is a mistake that makes the file unreviewable and turns every concurrent edit into a manual conflict. ## Verifying and its limits `git check-attr -a -- path` shows the expanded result, so you can confirm the macro took effect. Two limits are worth remembering. First, attributes change how operations behave from now on; blobs already stored are unaffected until content passes through Git again. Second, marking a file binary does nothing about its *size*: large assets still bloat clones, and the attribute is a diff and merge decision, not a storage one.
- Two branches both changed a file marked binary in Git. What does the merge produce and how do you resolve it?Git declares a conflict without attempting to combine content, leaving the current branch's version in the working tree as a tentative result. Resolution is a whole-file decision: inspect both sides, then run `git checkout --ours <path>` or `git checkout --theirs <path>`, or regenerate the artifact from source, and `git add` it. No conflict markers appear, because inserting them would corrupt the bytes.
- When would you unset only diff rather than applying the full binary macro?When the content is genuinely text that Git can merge safely but nobody wants to read in review, such as a lockfile or generated code. Unsetting diff alone keeps the ordinary three-way text merge and end-of-line handling while replacing the review output with a short notice. Applying the whole macro there would needlessly turn every concurrent edit into a manual conflict.
saying these in an interview costs you the question
- Thinks binary changes how the file is stored or compressed
- Believes Git still line-merges a binary-marked file
- Assumes it reduces repository size
- Applies it to ordinary source files to shorten diffs
- Says the content heuristic makes the attribute pointless