Inside Git: How It Works and the Role of the .git Folder

Most developers use Git every day, but very few know what Git is actually doing internally. We type commands like git add and git commit, but it feels almost magical.
Let’s open the black box and understand what’s really happening inside Git.
What Is the .git Folder?
When you run:
git init
Git creates a hidden folder called:
.git
This folder is the entire Git database for your project.
Your project is just files and folders. .git is what turns it into a Git repository.
If you delete .git, your project still exists — but Git forgets everything: no history, no branches, no commits.
What’s Inside the .git Folder?
A simplified view:

What these mean
| File / Folder | Purpose |
objects/ | Stores all Git data (commits, files, folders) |
refs/ | Stores branch and tag pointers |
HEAD | Points to your current branch |
index | The staging area |
config | Repo-specific settings |
Important Files and Folders
HEAD
Points to the current branch
Ultimately points to the latest commit
Example:
ref: refs/heads/main
config
Repository-specific configuration
Remote URLs, user info, settings
index
Also called the staging area
Stores what will go into the next commit
refs/
Stores references (pointers) to commits
Branches are just pointers to commits
refs/heads/main
refs/heads/feature-login
objects/ ⭐ (Most Important)
This is where Git stores all data.
Git Objects: Blob, Tree, Commit
Everything in Git is stored as an object.
There are three main object types you must understand.
1. Blob (Binary Large Object)
A blob represents:
The content of a file
Not the filename
Not permissions
Example:
console.log("Hello Git");
If two files have the same content, Git stores only one blob.
2. Tree
A tree represents:
A directory
File names
Folder structure
Pointers to blobs and other trees
Think of a tree as:
“This folder contains these files and subfolders.”
3. Commit
A commit represents:
A snapshot of your project
A pointer to a tree
Metadata:
Author
Date
Commit message
Parent commit(s)
A commit does not store files directly.
Relationship Between Commit, Tree, and Blob
Commit
↓
Tree (root directory)
↓
Blobs (file contents)
Visual representation:

How Git Tracks Changes
Git does not store diffs by default.
Instead:
Each commit points to a full tree
Trees point to blobs
Unchanged files reuse existing blobs
This makes Git:
Fast
Storage-efficient
Reliable
What Happens Internally During git add
Let’s say you modify a file:
index.js
When You Run:
git add index.js
Internally Git Does This:
Reads the file content
Creates a blob object
Stores it inside:
.git/objects/Updates the index (staging area) to point to that blob
📌 At this point:
File is staged
No commit exists yet
What Happens Internally During git commit
Now you run:
git commit -m "Add greeting message"
Internally Git Does This:
Creates a tree object from the staging area
Creates a commit object
Commit points to:
Tree
Parent commit
Updates
HEADto point to the new commit
Result:
HEAD → main → commit → tree → blobs
Internal Flow: git add → git commit
Working Directory
↓
git add
↓
Staging Area (index)
↓
git commit
↓
Commit → Tree → Blobs
How Git Uses Hashes to Ensure Integrity
Git uses SHA-1 hashes (moving toward SHA-256).
Each object:
Is hashed based on its content
Hash looks like:
e68ff1a28d...
Why This Matters
If content changes → hash changes
Data corruption is instantly detectable
History cannot be silently altered
This is why Git is extremely secure and reliable.