Git Attributes: Teaching Your Files Special Rules 🎭
The Story of the File Translator
Imagine you have a magic notebook that travels between different countries. In one country, people write sentences ending with two dots (like ..). In another country, they use just one dot (like .).
Without a translator, your notebook gets messy! Some pages have double dots, some have single dots, and nobody can read it properly anymore.
Git Attributes is like hiring a personal translator for your files. It tells Git: “When this file travels between computers, here’s exactly how to handle it!”
What is the .gitattributes File?
Think of .gitattributes as a rulebook that sits in your project folder. Just like how a school has rules posted on the wall, your project has this file to tell Git how to treat different files.
.gitattributes
This is just a simple text file. You create it, write your rules inside, and Git follows them automatically!
Where Does It Live?
graph TD A["Your Project Folder"] --> B[".gitattributes"] A --> C["README.md"] A --> D["code files"] A --> E["image files"] B --> F["Rules for ALL files below"]
The .gitattributes file sits at the root (top) of your project, like a security guard at the main entrance.
What Does It Look Like Inside?
# This is a comment
*.txt text
*.png binary
*.js text eol=lf
Each line is a simple rule:
- Pattern (like
*.txt) = which files - Attribute (like
text) = how to handle them
Line Ending Configuration: The Great CRLF Battle
The Problem: Two Kingdoms with Different Rules
Story Time! 🏰
Long ago, there were two kingdoms:
- Windows Kingdom 🪟 - They end every sentence with TWO characters:
\r\n(called CRLF - Carriage Return + Line Feed) - Mac/Linux Kingdom 🐧 - They end every sentence with ONE character:
\n(called LF - Line Feed)
When people from both kingdoms work on the same scroll (code file), chaos happens! One person’s scroll looks different from another’s, even though they wrote the same words.
The Solution: A Universal Translator
.gitattributes can fix this:
# Force all text files to use LF
* text=auto
# Specifically handle common file types
*.js text eol=lf
*.css text eol=lf
*.html text eol=lf
*.md text eol=lf
*.json text eol=lf
What Do These Rules Mean?
| Attribute | Meaning |
|---|---|
text |
“This is a text file, translate line endings!” |
text=auto |
“Git, figure out if it’s text automatically” |
eol=lf |
“Always save with LF (Unix style)” |
eol=crlf |
“Always save with CRLF (Windows style)” |
Real Example
# .gitattributes file content
# All text files get normalized
* text=auto
# Shell scripts MUST use LF
*.sh text eol=lf
# Windows batch files MUST use CRLF
*.bat text eol=crlf
Why does this matter?
- Shell scripts (
.sh) break on Windows if they have CRLF - Batch files (
.bat) can break on Windows if they have LF
The rulebook keeps everyone happy! 🎉
Binary File Handling: Some Files Shouldn’t Be Translated
The Art Gallery Analogy 🖼️
Imagine you have:
- Letters (text files) → You CAN translate these
- Paintings (images) → You CANNOT translate these!
If you try to “translate” a painting, you destroy it. Binary files (images, videos, compiled code) are like paintings.
Telling Git What’s Binary
# Images are binary - DON'T touch them!
*.png binary
*.jpg binary
*.gif binary
*.ico binary
# Fonts are binary
*.woff binary
*.woff2 binary
*.ttf binary
# Compiled/compressed files
*.zip binary
*.exe binary
*.pdf binary
What Does binary Mean?
When you mark a file as binary, you’re telling Git:
- ❌ Don’t try to show “changes” line by line
- ❌ Don’t convert line endings
- ❌ Don’t try to merge changes
- ✅ Just store it exactly as-is
graph TD A["File Types"] --> B["Text Files"] A --> C["Binary Files"] B --> D["Can see line changes"] B --> E["Line endings converted"] C --> F["No line-by-line diff"] C --> G["Stored exactly as-is"]
The -text Shorthand
These two lines do the same thing:
*.png binary
*.png -text -diff
The word binary is just a shortcut!
Git LFS Basics: A Storage Warehouse for Big Files
The Problem: Big Files Make Git Slow 🐌
Story Time! 📦
Imagine your project is a backpack. Text files are like papers - light and easy to carry. But what if you need to carry:
- Video files (bowling balls 🎳)
- High-resolution images (bricks 🧱)
- Game assets (furniture 🪑)
Your backpack becomes impossible to carry! Every time you share it with a friend, they have to carry ALL the heavy stuff too.
The Solution: Git LFS (Large File Storage)
LFS = Large File Storage
Think of it as a storage warehouse:
- Your backpack (Git repo) carries a receipt (pointer)
- The actual heavy item stays in the warehouse (LFS server)
- When you need the item, you show the receipt and get it
graph TD A["Your Git Repo"] --> B["Small text files"] A --> C["LFS Pointer files"] C --> D["LFS Warehouse"] D --> E["Actual big files"]
Setting Up Git LFS
Step 1: Install LFS (one-time setup)
git lfs install
Step 2: Tell Git LFS what to track
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.zip"
Step 3: This creates/updates .gitattributes!
# .gitattributes (auto-generated)
*.psd filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
What Does the LFS Line Mean?
*.psd filter=lfs diff=lfs merge=lfs -text
| Part | Meaning |
|---|---|
*.psd |
Apply to all Photoshop files |
filter=lfs |
Use LFS to store/retrieve |
diff=lfs |
Use LFS for showing changes |
merge=lfs |
Use LFS for merging |
-text |
Don’t treat as text file |
Why Use Git LFS?
| Without LFS 😰 | With LFS 😊 |
|---|---|
| Repo size: 2GB | Repo size: 50MB |
| Clone time: 30 min | Clone time: 2 min |
| Everyone downloads ALL versions of big files | Only download what you need |
Putting It All Together: A Complete .gitattributes
Here’s a real-world example you can use:
# Auto-detect text files
* text=auto
# === Source Code ===
*.js text eol=lf
*.jsx text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.css text eol=lf
*.html text eol=lf
*.json text eol=lf
*.md text eol=lf
*.yml text eol=lf
# === Shell Scripts ===
*.sh text eol=lf
*.bash text eol=lf
# === Windows Scripts ===
*.bat text eol=crlf
*.cmd text eol=crlf
# === Binary Files ===
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.woff binary
*.woff2 binary
*.ttf binary
*.eot binary
*.pdf binary
# === Git LFS ===
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
Quick Summary
| Concept | What It Does | Example |
|---|---|---|
.gitattributes |
Rulebook for file handling | Put in project root |
text |
Enable line ending conversion | *.js text |
eol=lf |
Force Unix line endings | *.sh text eol=lf |
eol=crlf |
Force Windows line endings | *.bat text eol=crlf |
binary |
Store as-is, no conversion | *.png binary |
filter=lfs |
Use Git LFS for storage | *.psd filter=lfs... |
You Did It! 🎉
Now you understand:
✅ Gitattributes file - Your project’s rulebook
✅ Line ending configuration - Keeping Windows and Mac/Linux friends happy
✅ Binary file handling - Protecting images and other non-text files
✅ Git LFS basics - Storing heavy files in a warehouse
Your files now travel safely between any computer, and your repo stays fast and clean! You’re a Git Attributes master! 🏆
