You know git add and git commit. But what actually happens when you run these commands?
Let's look inside Git and understand how it really works.
The .git Folder: Git's Brain
When you run git init, Git creates a hidden .git folder. This folder is where Git stores everything about your project.
See it:
ls -la # On Linux/Mac
dir /a # On Windows
Inside .git
.git/
├── HEAD # Points to current branch
├── config # Repository settings
├── objects/ # All your data (commits, files)
├── refs/ # Branch pointers
├── index # Staging area
└── logs/ # Change history
Most important:
- objects/: Where Git stores all data
- refs/: Where branch pointers live
- HEAD: Shows your current position
- index: Your staging area
Rule: Never manually edit files in .git. Let Git handle it.
Git Objects: The Three Types
Git stores everything as objects. Three types matter:
1. Blob (File Content)
Stores file content only. No filename, no folders—just content.
Example:
File index.html with content "Hello World" becomes a blob containing just "Hello World".
2. Tree (Directory Structure)
Stores folder structure. Lists files and their locations.
Example:
"This folder has index.html (blob abc123) and style.css (blob def456)."
3. Commit (Snapshot)
Stores project snapshot: which tree, who made it, when, and why.
Example:
"Project looked like this. Author: John. Date: Jan 15. Message: Add homepage."
How They Connect
Commit
↓ points to
Tree (folder)
↓ contains
Blobs (files)
Real example:
Your project:
├── index.html ("Hello")
└── style.css ("body { margin: 0; }")
Git stores:
Commit abc123 → Tree xyz789 → Blob aaa111 ("Hello")
→ Blob bbb222 ("body { margin: 0; }")
Git Uses Hashes
Every object gets a unique 40-character ID called a hash.
Example:
"Hello World" always creates hash: 980a0d5f19a64b4b30a87d4206aade58726b60e3
Why?
- Different content = different hash
- Content changes? Hash changes
- Git knows immediately if data is corrupted
- Same content stored only once
What Happens: git add
You run:
git add index.html
Git does:
- Reads file content
- Creates blob object with hash
-
Stores blob in
.git/objects/ - Updates index (staging area)
Result: File is staged, ready to commit.
The file content is now safely stored in Git, but not committed yet.
What Happens: git commit
You run:
git commit -m "Add homepage"
Git does:
- Creates tree object from staging area
- Creates commit object pointing to tree
- Adds metadata: author, date, message, parent commit
- Generates commit hash
- Updates branch pointer to new commit
Result: Your changes are permanently saved.
How Git Tracks Changes
Common myth: Git stores the differences between versions.
Truth: Git stores complete snapshots.
But doesn't that waste space?
No! Here's why:
- Reuses unchanged files: If a file doesn't change, Git points to the old blob
- Compression: Git compresses everything
- Smart storage: Git packs objects efficiently
Example:
Commit 1:
- index.html (blob aaa)
- style.css (blob bbb)
Commit 2: (only index.html changed)
- index.html (blob ccc) ← new
- style.css (blob bbb) ← reused!
The Staging Area (Index)
The index is a file at .git/index containing your next commit.
Why have staging?
Control. You can:
- Stage only some files
- Review before committing
- Build thoughtful commits
Example:
# Edit two files
echo "New" > file1.txt
echo "More" > file2.txt
# Stage only file1
git add file1.txt
# Commit only file1
git commit -m "Update file1"
# file2 remains uncommitted
HEAD: Your Position
HEAD is a pointer showing where you are.
Location: .git/HEAD
Content:
ref: refs/heads/main
Means: "You're on the main branch."
Switch branches:
git checkout feature
HEAD updates to: ref: refs/heads/feature
Branches Are Just Pointers
A branch is a file containing a commit hash.
Location: .git/refs/heads/main
Content:
f3a8d91c8a7d4e5f6b2c3d4e5f6a7b8c9d0e1f2a
That's it. Just the latest commit hash.
Creating a branch:
git branch feature
Git creates a new file with the current commit hash. Super fast.
Complete Flow
1. Edit file:
echo "Hello" > readme.txt
File in working directory.
2. Stage it:
git add readme.txt
Git creates blob, updates index.
3. Commit:
git commit -m "Add readme"
Git creates tree and commit objects, updates branch pointer.
Visual:
Working Directory
↓ (git add)
Staging Area
↓ (git commit)
Repository
↓
Branch updated
Try It Yourself
# Create repo
git init test-repo
cd test-repo
# Create file
echo "Test" > file.txt
git add file.txt
# Find the blob hash
git ls-files -s
# Shows: 100644 <hash> 0 file.txt
# View blob content
git cat-file -p <hash>
# Shows: Test
# Commit and explore
git commit -m "First commit"
git log --oneline # Get commit hash
git cat-file -p <commit-hash> # View commit object
Key Takeaways
- .git stores everything - Your entire history is here
- Three objects: blob, tree, commit - Foundation of Git
- Hashes identify content - Same content = same hash
- Staging prepares commits - Build commits carefully
- Branches are pointers - Lightweight and fast
- Git stores snapshots - Not differences
Mental Model
Think of Git as a tree:
C3 (main)
|
C2
/ \
C1 C1' (feature)
- Circles = commits
- Each commit points to a tree
- Each tree points to blobs
- Branches = labels on commits
Why This Matters
Understanding internals helps you:
- Debug problems confidently
- Use advanced features
- Recover lost work
- Explain Git to others
- Stop fearing Git
Final Thoughts
Git is elegant underneath:
- Files → blobs
- Folders → trees
- Snapshots → commits
- Labels → branches
Once you see this, Git makes sense.
You're not memorizing commands anymore. You understand what they do.
Resources:
- Git Book: git-scm.com/book
- Experiment with
git cat-file -p - Break things in test repos (best way to learn!)
Top comments (0)