Most beginners learn Git by memorizing commands like git add, git commit, and git push. But sooner or later, questions arise:
- Where does Git actually store my code?
- What is the mysterious
.gitfolder? - How does Git know what changed?
- Why does Git talk so much about hashes?
In this article, we'll open Git's black box and understand how Git works internally in simple terms. No advanced theory. No magic. Just a clear mental model.
How Git Works Internally (Big Picture)
At its core, Git is a content addressable database.
That sounds complicated, but here's the simple idea:
Git doesn't track files it tracks snapshots of content.
Every time you commit:
- Git takes a snapshot of your project
- Stores it safely
- Links it to previous snapshots
All of this data lives inside one folder:
.git/
If you understand this folder, you understand Git.
What Is the .git Folder and Why Does It Exist?
When you run:
git init
Git creates a hidden folder called .git.
This folder is the repository.
If you delete
.git, your project becomes a normal folder Git history is gone.
What does .git contain?
A simplified view:
.git/
├── objects/
├── refs/
├── HEAD
├── index
└── config
Don't panic we'll focus only on what matters.
Why does Git need this folder?
The .git folder stores:
- Your entire commit history
- All versions of every file
- Branch information
- Metadata about commits
Your working directory is just a checkout of what's inside .git.
Git Objects: Blob, Tree, Commit (The Building Blocks)
Git stores everything as objects. There are only three core object types you need to understand.
Blob: File Content
A blob stores the contents of a file.
Important:
- Blob does not store the filename
- Only the raw content
Example:
console.log("Hello Git");
If two files have the same content, Git stores only one blob. This is how Git saves space.
Tree: Folder Structure
A tree represents a directory.
It:
- Maps filenames to blobs
- Can point to other trees (subfolders)
Think of a tree like:
project/
├── index.js (blob)
└── src/
└── app.js (blob)
Trees tell Git:
- Which files exist
- Their names
- Their structure
Commit: A Snapshot
A commit is a snapshot of your project.
It contains:
- A reference to a tree
- A reference to the parent commit
- Author info
- Commit message
- Timestamp
Visually:
Commit
↓
Tree
↓
Blobs
Each commit links to the previous one, forming Git's history.
How Git Tracks Changes (Not Diffs!)
Many people think Git stores file differences.
It doesn't.
Git stores snapshots, not diffs.
When you commit:
- Git checks each file
- If content is unchanged → reuse old blob
- If content changed → create new blob
That's why Git is fast and efficient.
What Happens Internally During git add
When you run:
git add file.txt
Git does NOT create a commit.
Instead, it:
- Reads the file content
- Creates a blob object
- Stores it in
.git/objects - Updates the index (staging area)
Mental model:
git add= "Prepare this snapshot for the next commit"
The index is a temporary holding area between:
- Working directory
- Repository history
What Happens Internally During git commit
When you run:
git commit -m "My commit"
Git:
- Takes everything from the index
- Builds a tree
- Creates a commit object
- Updates
HEADto point to the new commit
That's it.
Your history is now permanently recorded (unless you rewrite it).
How Git Uses Hashes to Ensure Integrity
Every Git object is identified by a SHA-1 hash (40 characters).
Example:
e83c5163316f89bfbde7d9ab23ca2e25604af290
Why hashes matter
Hashes ensure:
- Integrity → content cannot be silently changed
- Uniqueness → same content = same hash
- Security → tampering breaks history
If even one character changes, the hash changes completely.
This is why Git history is trustworthy.
When you finally understand Git internals and realize commits are just pointers to trees
Building the Right Mental Model of Git
Instead of memorizing commands, remember this:
Git is a database of snapshots stored inside
.git.
-
.git= brain of Git - Blob = file content
- Tree = folder structure
- Commit = snapshot + history
- Hash = identity + integrity
Commands like add, commit, and checkout are just ways to move between snapshots.
Final Thoughts
Understanding Git internally:
- Makes debugging easier
- Removes fear of "breaking Git"
- Helps you learn advanced topics faster
You don't need to remember everything just remember how the pieces fit together.
If you found this helpful, try exploring:
ls -la .git/objects/
You'll be surprised how much Git suddenly makes sense.


Top comments (0)