Chapter 44: Git .gitattributes
1. What exactly is .gitattributes?
It is a normal text file (just like .gitignore) that lives in your repository (usually in the root).
Git reads it automatically and applies special rules to matching files / patterns.
The most common things people set in .gitattributes:
| Purpose | Typical line in .gitattributes | What it actually does |
|---|---|---|
| Force text files to use LF endings | *.txt text eol=lf *.md text eol=lf | Always checkout with LF, commit with LF — prevents Windows CRLF corruption |
| Force Windows-style CRLF | *.bat text eol=crlf *.cmd text eol=crlf | Windows batch scripts must keep CRLF |
| Treat files as binary (no diff) | *.png binary *.jpg binary *.zip binary | Git never tries to diff them (saves space, avoids corruption) |
| Enable word-diff / better blame | *.json text *.xml text | Treat as text even if they look binary — enables line-by-line blame & readable diffs |
| Delta compression for large text | *.min.js text diff | Allow delta compression even for minified files |
| Custom diff driver | *.ipynb diff=ipynb | Use special Jupyter notebook diff tool |
2. The two most important attributes (used in 95% of real projects)
| Attribute | Meaning | Most common real-world usage (2026) |
|---|---|---|
| text | This is a text file — Git should do line-ending conversion | *.sh text eol=lf *.py text eol=lf *.js text *.json text |
| eol=lf / eol=crlf | Force checkout line endings to LF or CRLF | *.sh text eol=lf (Unix scripts must have LF) *.bat text eol=crlf (Windows scripts) |
| binary | Treat as binary — no line-ending conversion, no diff, no merge | *.png binary *.jpg binary *.pdf binary *.zip binary *.exe binary |
3. Real Example – Create & Use .gitattributes Right Now
Step 1 – Make a small demo project
|
0 1 2 3 4 5 6 7 8 |
mkdir gitattributes-demo cd gitattributes-demo git init |
Step 2 – Create mixed files
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Text files that should always use LF echo "# My Awesome Project" > README.md echo "console.log('Hello');" > app.js # Windows batch file (needs CRLF) echo "@echo off" > run.bat echo "echo Hello from Windows" >> run.bat # Binary file echo "fake binary data" > image.png # pretend it's binary # JSON that looks binary but should be text echo '{"name": "project"}' > config.json |
Step 3 – Create .gitattributes
Create file .gitattributes in root:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# Force all common text files to LF line endings (prevents Windows corruption) *.md text eol=lf *.js text eol=lf *.ts text eol=lf *.py text eol=lf *.sh text eol=lf *.yaml text eol=lf *.yml text eol=lf *.json text eol=lf *.xml text eol=lf # Windows scripts must keep CRLF *.bat text eol=crlf *.cmd text eol=crlf # Binaries - no diff, no line-ending conversion *.png binary *.jpg binary *.jpeg binary *.gif binary *.ico binary *.zip binary *.exe binary *.dll binary *.so binary *.dylib binary # Force JSON/XML to be treated as text (better blame & diff) *.json text *.xml text |
Step 4 – See the magic
|
0 1 2 3 4 5 6 7 |
git add . git status |
Git now knows:
- README.md, app.js, config.json → treated as text with LF
- run.bat → treated as text but with CRLF
- image.png → treated as binary (won’t show in diff)
Commit:
|
0 1 2 3 4 5 6 |
git commit -m "chore: add .gitattributes and initial files" |
Step 5 – Test line-ending behavior
On Windows machine → checkout repo → open README.md in Notepad → it shows LF endings (Git converted automatically)
On Linux/macOS → same file → LF (no change)
If someone changes run.bat on Linux → Git forces CRLF on checkout → Windows users happy.
4. Common .gitattributes Patterns (copy-paste ready – 2026)
Minimal modern JavaScript/TypeScript project
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# Text files - always LF * text=auto eol=lf *.js text eol=lf *.ts text eol=lf *.tsx text eol=lf *.json text eol=lf *.md text eol=lf *.yml text eol=lf *.yaml text eol=lf # Binaries *.png binary *.jpg binary *.svg binary *.ico binary *.woff binary *.woff2 binary *.ttf binary *.eot binary # Build output dist/ build/ |
Python project
|
0 1 2 3 4 5 6 7 8 9 10 11 |
*.py text eol=lf *.pyi text eol=lf *.pyc binary __pycache__/ *.egg-info/ *.egg |
5. Common Gotchas & Fixes (2026 reality)
| Problem | Reason & Fix |
|---|---|
| File still tracked after adding to .gitattributes | Already committed → git rm –cached filename → commit |
| Line endings still wrong | Use text eol=lf or text=auto — text=auto lets Git guess but prefers LF |
| Huge repo because of images/PSDs | Add *.psd binary + use Git LFS for large files |
| Teammate on Windows has CRLF everywhere | Add * text=auto eol=lf at top + commit .gitattributes |
| Diff shows entire minified JS file changed | Add *.min.js text so Git treats it as text |
Got the .gitattributes feeling now?
.gitattributes = Git’s per-file rule book — controls line endings, binary/text treatment, diff behavior, and more
It’s one of the first three files every serious project creates (along with .gitignore and README.md).
Next?
- Want a ready-made .gitattributes for your specific stack (React, Python, Java, etc.)?
- See how to use Git LFS with .gitattributes for large files?
- Or wrap up with one final big summary of all Git concepts we covered?
Just tell me — we’ll finish strong. You’ve now gone from zero to advanced Git — incredible journey! 🚀
