How git works
How Git Works Internally: Understanding the
.git
Folder and Git Objects
Most developers learn Git by memorizing commands — git add, git commit, git push, etc. But once something goes wrong, confusion hits. The real power of Git reveals itself when you understand how it works internally, especially what lives inside the mysterious .git folder.
This post will help you build a mental model of Git’s internals without drowning in implementation details.
1. What Exactly Is the
.git
Folder?
When you run git init, Git creates a hidden folder named .git in your project directory.
That folder is the repository.
Your working directory (the visible project files) is just a view of the repo.
The .git directory stores everything Git needs, including:
✔ Your commit history
✔ Branches & tags
✔ Objects (blobs, trees, commits)
✔ Staging area info
✔ Configuration & HEAD reference
If you delete .git, the entire repo is gone.
🗂 High-level structure of
.git
.git/
├── HEAD
├── config
├── description
├── hooks/
├── info/
├── objects/
├── refs/
│ ├── heads/
│ ├── tags/
└── index
You don’t need to remember every file — just understand that this folder = Git’s brain.
2. Git Is Not a Diff-Based System — It’s a Snapshot System
A common misconception is:
“Git stores diffs between files.”
Nope.
Git stores snapshots of your files, and only new snapshots when content actually changes.
This is important because Git achieves:
✔ Speed
✔ Integrity
✔ Efficient storage
3. Git Objects: The Real Building Blocks
Git stores data inside .git/objects/ as objects, identified by a SHA-1 hash.
There are four object types:
| Object | Meaning |
| blob | File contents |
| tree | Directory structure (like a folder) |
| commit | A snapshot + metadata |
| tag | Human-friendly labels for commits |
Let’s break down the main three:
3.1 Blob — represents file content
A blob stores file data and nothing else (no filename, no permissions).
For example, two identical files = one blob.
Blob: "console.log('Hello')"
Hash: e.g. a1b2c3...
3.2 Tree — represents directories
A tree stores:
✔ filenames
✔ pointers to blobs or subtrees
✔ file permissions
Example tree structure:
tree (root)
├── file1.js → blob hash
└── src/
└── index.js → blob hash
3.3 Commit — represents a snapshot
A commit stores:
✔ root tree hash
✔ parent commit(s)
✔ author info
✔ message
✔ timestamp
Example (conceptual):
commit
├── tree: 9ad12f...
├── parent: 7db32e...
├── author: Satyam
└── message: "Initial commit"
4. How Git Tracks Changes (Internally)
Git has three main areas:
┌─────────────┬───────────────┬────────────┐
│ Working Dir │ Staging Area │ Repository │
└─────────────┴───────────────┴────────────┘
| | |
your files index .git/objects
Workflow:
Edit files → working directory
git add → staging area (index)
git commit → repository (objects)
5. What Happens During
git add
?
When you run:
git add file.txt
Git does two things:
(A) Create a blob object
Stores the content of file.txt in .git/objects/ and names it with its hash.
(B) Update the index file
Adds an entry mapping:
filename → blob hash
But no commit is created yet.
So git add prepares data.
Internal flow:
Working Directory → Blob (object)
Blob hash → Index (staging)
6. What Happens During git commit?
When you commit, Git:
Reads staged blobs from index
Creates tree objects
Creates a commit object pointing to that tree
Updates the branch reference
Internal flow:
Index → Tree → Commit → refs/heads/master
If this commit has a parent, Git stores that link too.
7. Git Uses Hashes for Integrity
Git generates a unique SHA-1 hash from object contents.
This means:
✔ If you change a file → hash changes
✔ Impossible to modify history unnoticed
✔ Corruption is detectable
This is why Git provides content-addressable storage.
8. Visual Model of Git Objects (Diagram)
Commit graph (ASCII view):
Commit C (hash: c3)
|
└── Tree T3
├── file1 → blob b1
└── file2 → blob b2
|
Parent → Commit B (hash: b2)
|
└── Tree T2 ...
You can create a UI diagram like this for the article.
9. The
HEAD
File and Branches
HEAD tells Git where you currently are, e.g.:
ref: refs/heads/main
Branches are just text files pointing to commit hashes:
refs/heads/main → c3f9a1...
Lightweight and cheap.
10. Why This Mental Model Helps
With this understanding, confusing scenarios make sense:
✔ Why two files with same contents don’t increase repo size
✔ Why Git checkout is fast → just switches commit trees
✔ Why rebasing changes commit hashes → new commit objects
✔ Why history integrity is guaranteed via hashes
Conclusion
Git isn’t magic — it’s a simple system of:
✔ Blobs for file contents
✔ Trees for folders
✔ Commits for snapshots
✔ Hashes for integrity