Inside Git: How It Works and the Role of the .git Folder
What Git Really Is (Under the Hood)
When you use commands like git add and git commit, Git doesn’t just record text - it builds a structured database of objects inside a special hidden folder called .git. That folder is your entire Git repository’s history, metadata, objects, pointers, and logic.
So, instead of thinking of Git as “a set of commands,” it’s more like:
A very smart snapshot‑based version database*.*
Git captures the state of your project at points in time, and that’s what makes it reliable, fast, and powerful.
What the .git Folder Is and Why It Exists
The .git folder lives at the root of your project once you run git init. It holds everything Git needs to track changes and manage history:
All objects (blobs, trees, commits)
Index (staging area)
Refs (branch pointers)
Logs and configs
In short: .git is the Git repository itself - not just a folder, but the whole Git database.
Git’s Core Object Types
Git stores every bit of content and history as objects inside .git/objects. These are named by a hash (a unique fingerprint) based on their contents - which is why Git never really loses or corrupts history.
The main internal objects are:
Blob - File Contents
Stores the raw data of a file
No filename, no directory info
Identified by a SHA‑1 hash of the content
Example: if you run git add file.txt, Git reads the file and creates a blob object with its contents.
Tree - Directory Snapshot
A tree object represents the structure of a directory - it points to:
Blobs (files)
Other trees (subdirectories)
Filenames and file modes (permissions)
In other words, tree objects are Git’s way of modeling the folder hierarchy of your project.
Commit - Snapshot + History
A commit object ties everything together. A commit contains:
A reference to a tree object (the root of the project at that moment)
A pointer to the parent commit (the previous snapshot)
Metadata like author, timestamp, and a message
Commits form a history chain where each commit points back to the snapshot that came before it.
How Git Tracks Changes
Git doesn’t store deltas (line‑by‑line changes) like some older systems. Instead, Git captures snapshots of the project state at each commit - but because it stores content efficiently (reusing blobs and trees when nothing changes), it still uses space well.
Here’s a mental model you can use to visualize this:
Commit
↓
Tree
↓
Blobs
So commits store tree snapshots, and trees connect to blobs (file contents).
What Happens Internally During git add
When you run:
git add file.txt
Git does the following:
Reads
file.txtCreates a blob in
.git/objects(or reuses an existing one if content is identical)Stores the blob’s SHA‑1 hash
Updates the index (staging area) to point to this blob for the next commit
So git add doesn’t create a commit — it prepares (or freezes) the data for the next commit.
Working Directory
↓ git add
Staging Area (index) ---> blob stored in .git/objects
What Happens Internally During git commit
When you run:
git commit -m "message"
Git does:
Looks at everything in the staging area
Builds a tree object representing the directory structure
Creates a commit object pointing to that tree
Links it to the previous commit (parent)
Updates the branch ref (e.g.,
main) to the new commit hash
This is how Git records history - not files, but snapshots tied together by hashes.
Staging Area
↓ git commit
Tree created
↓
Commit created
How Git Uses Hashes to Ensure Integrity
Every Git object is identified by a SHA‑1 hash - a cryptographic fingerprint of its content.
Same content → same hash
A tiny change → completely different hash
Hash changes automatically if anything inside changes
This ensures that Git can detect tampering or corruption, and guarantees that two developers having the same commit hash truly have the same snapshot.
Because of hashes:
Identical files are stored only once (deduplication)
Changes are easy to verify
History is reliable and reproducible
Internal Flow Diagram — How Git Stores Things
You edit file
│
v
Working Directory (changed file)
│ git add
v
Staging Area (index) → blob created in .git/objects
│ git commit
v
Tree object created
↓
Commit object created → branch pointer updated
This flow shows how Git moves from file edit → staging → commit internally.
Summary: Git’s Mental Model
Here’s the conceptual model to remember:
Blob = Content (file snapshot)
Tree = Structure (directory snapshot)
Commit = History (snapshot linked to previous ones)
.git folder = Database (all objects + refs + metadata)
Hashes = Trust (identifying objects by content)