.gitattributes File
.gitattributes tells Git how to handle specific paths differently — things like line-ending conversion, how to diff binary files, which files should be treated as “generated” (and hidden from PR reviews), and many advanced features. Where .gitignore says “Git, leave these alone”, .gitattributes says “Git, treat these specially”.
Where it lives
Put a file called .gitattributes in the root of your repo (or in any subfolder). Commit it. Its rules apply to all contributors automatically — that is the whole point.
File format
One pattern per line + attributes
pattern attribute1 attribute2=value -attribute3 # comments start with #
The pattern follows the same rules as .gitignore. The attributes change how Git handles matching files.
The most common use: line endings
Force LF for cross-platform repos
# Default — let Git decide based on content * text=auto # Force LF for these (shell scripts must have LF on Linux) *.sh text eol=lf *.bash text eol=lf Makefile text eol=lf # Force CRLF for Windows scripts *.bat text eol=crlf *.cmd text eol=crlf # Treat these as binary (no line-ending conversion, no diff) *.png binary *.jpg binary *.pdf binary *.zip binary *.woff2 binary
The text and binary attributes
text— file is treated as text (line endings normalised on commit, converted on checkout).text=auto— Git decides based on content sniffing.eol=lf or eol=crlf — force a specific line ending on checkout.
binary— shortcut for-text -diff— never convert, never diff.
Showing better diffs for specific filetypes
Custom diff drivers
*.go diff=golang *.py diff=python *.html diff=html *.css diff=css *.md diff=markdown *.json diff=json
Each of these tells Git: “when diffing this file type, use the language-aware function header detector.” git diff will then show function names in hunk headers, making review easier.
Marking files as generated
linguist-generated tells GitHub to hide it
# Hide minified bundles from PR diffs (GitHub-specific) dist/** linguist-generated=true **/*.min.js linguist-generated=true **/*.bundle.js linguist-generated=true package-lock.json linguist-generated=true yarn.lock linguist-generated=true # Override language detection — GitHub may misidentify these *.h linguist-language=C++ src/vendor/** linguist-vendored=true docs/** linguist-documentation=true
Export-ignore — exclude files from archives
# When someone runs 'git archive' to make a tarball, skip these .github/ export-ignore tests/ export-ignore .editorconfig export-ignore .eslintrc.js export-ignore
Filters — automate content transformation
Smudge / clean filters
*.lfs filter=lfs diff=lfs merge=lfs -text # used by Git LFS # Strip Jupyter notebook outputs on commit *.ipynb filter=nbstripout
Filters run a “clean” program on commit and a “smudge” program on checkout. Combined with git config filter.X.clean and filter.X.smudge, you can transparently transform files.
Merge strategies per file
# Always take the version from the branch being merged in CHANGELOG.md merge=ours # Refuse to auto-merge — flag a conflict instead (use sparingly) *.config merge=binary
Limiting language detection on GitHub
Common linguist overrides
# Vendor directories — don't include in language stats vendor/** linguist-vendored third_party/** linguist-vendored # Documentation docs/** linguist-documentation *.md linguist-documentation
Verifying attributes
What attributes apply to a path?
git check-attr -a src/app.js # src/app.js: diff: javascript # src/app.js: text: auto git check-attr text eol -- src/app.js # src/app.js: text: auto # src/app.js: eol: unspecified
Applying attribute changes to existing files
One-time renormalization
# After editing .gitattributes git add --renormalize . git commit -m "Renormalize line endings per .gitattributes"
A practical .gitattributes for most repos
Drop this in your repo root
# ─── Line endings ─── * text=auto *.sh text eol=lf *.bash text eol=lf *.bat text eol=crlf *.cmd text eol=crlf # ─── Binary file types ─── *.png binary *.jpg binary *.jpeg binary *.gif binary *.webp binary *.ico binary *.pdf binary *.zip binary *.gz binary *.tar binary *.woff binary *.woff2 binary # ─── Hide noisy files from PR diffs ─── package-lock.json linguist-generated yarn.lock linguist-generated *.min.js linguist-generated dist/** linguist-generated # ─── Vendor / docs ─── vendor/** linguist-vendored third_party/** linguist-vendored docs/** linguist-documentation