gitattributes
How to define per-file attributes in Git
.gitattributes is a configuration file that defines per-file attributes in a Git repository. It is less visible than a branching strategy or .gitignore, but when a repository is shared across a team it is the key tool for finely controlling text encoding, filters, merge strategies, line endings (EOL), and binary handling. Git decides “text or binary?” automatically at source-control time, but the rules differ from project to project, which often causes errors. gitattributes states each file’s intended attributes and reduces the uncertainty of “Git will probably figure it out”.
What the EOL problem really is
Line-break characters differ by operating system.
- LF (
\n): Unix, Linux, macOS - CRLF (
\r\n): Windows
Editing the same file on different operating systems mixes the line breaks, so “the whole diff is line endings”, or scripts fail to run. Git has a global core.autocrlf option, but it is not fine-grained at the team, repository, or file level. So we use gitattributes’ eol attribute to implement a policy like “always LF inside the repository; convert to the OS only on checkout”.
eol attribute examples
# Default policy: text files are always stored as LF
* text eol=lf
# Windows-only batch scripts keep CRLF
*.bat text eol=crlf
# Bash scripts are always LF
*.sh text eol=lf
These rules create the flow “convert to LF on commit → convert to the local environment on checkout”, which minimises line-ending disputes.
Managing binary files
Repositories hold more than source code: images, fonts, executables, archives and other binary assets live there too. Text-only settings cannot avoid the following problems.
- A file mistaken for text undergoes EOL conversion and its data is corrupted.
- Git tries to diff and merge it, which slows things down or produces conflicts.
- When large files change slightly in every past commit, the repository balloons.
The binary and -text attributes
The simplest fix is to declare the extension binary so Git never attempts EOL conversion or automatic merging.
# Treat images, fonts, archives and friends as binary
*.png binary
*.jpg binary
*.ttf binary
*.zip binary
*.7z binary
# `binary` is internally equivalent to `-text diff`
Attribute meanings:
| Attribute | Meaning |
|---|---|
binary | Turns off the text attribute (-text) and turns off diffing. |
-text | Turns off text conversion (including EOL) only. diff/merge can stay on. |
The heart of both
binaryand-textis “no CRLF ↔ LF conversion”. You can also combine the two attributes, as in-text diff, for finer control.
Working with Git LFS
Once you accumulate large assets, Git LFS (Large File Storage) enters the picture, and gitattributes plays an essential role alongside it.
# Manage PSD files over 10 MB through LFS
*.psd filter=lfs diff=lfs merge=lfs -text
With filter=lfs set like this, commits store a small pointer file instead of the actual data. The real binary lives on the LFS server, which keeps the repository small.
Its relationship with core.autocrlf
-
core.autocrlf=false(recommended): means you intend to control line-ending conversion through gitattributes alone. -
core.autocrlf=trueorinput: an active global setting can conflict with.gitattributesrules. To avoid confusing teammates, it is safer to state the EOL and binary policy at the repository level and tell everyone to setcore.autocrlf=false.
Practical checklist
- When creating a new repository, document the baseline EOL and binary policy in
.gitattributes. - When adopting it in an existing repo, announce it in advance — it produces a large commit of line-ending and binary attribute changes.
- Check that your IDE does not have “convert line endings on save” enabled, and that it is not mistaking binary extensions for text.
- Set
git config --global core.autocrlf falseexplicitly in the CI pipeline, and ship Git LFS alongside it if needed.
Wrapping up
Line endings and binary file handling start as the mild annoyance of “it works, but the diff is a mess” and can escalate into unexpected problems like build failures and a bloated repository. Declaring the EOL and binary policy in .gitattributes and getting the team, CI, and IDE to speak with one voice is the surest prevention. Set it up once and you sharply reduce the awkward situations of “debugging because of line endings” or “recovering a corrupted binary”.