Understanding How Git Works Under the Hood
A deep dive into Git's internal mechanics: object model, staging, commits, trees, and more. Learn how Git really works under the hood.
Introduction
Git is more than just a version-control tool it’s a content-addressable filesystem and a set of primitives upon which distributed collaboration is built. In this deep dive, we’ll strip away the “git add/commit/push” gloss and peer into Git’s innards: its object model, storage mechanics, and the workflows that emerge from them. By the end, you’ll appreciate why Git is fast, resilient, and remarkably flexible.
1. The Three States: Working Directory, Index, and Repository
-
Working Directory
- Your editable files on disk.
-
Index (Staging Area)
- A cached snapshot of what will go into the next commit.
-
Repository (.git folder)
- Contains all commits, objects, refs, and metadata.
When you run git add, you’re copying changes from the Working Directory into the Index. A git commit transforms the Index into a new commit object inside the Repository.
2. The Git Object Model
At its core, Git stores four object types, each identified by a SHA-1 (or SHA-256) hash of its content:
-
Blob
-
Represents file data (contents only).
-
No filename or metadata-just raw bytes.
-
-
Tree
- A directory listing: maps filenames to blob or subtree SHA hashes plus permissions.
-
Commit
- Points to one tree (the snapshot of your entire project), contains metadata (author, message, timestamp) and zero or more parent commit hashes.
-
Tag
- A named pointer to a specific commit, optionally signed.
Why content-addressable?
Because the SHA is computed over the contents, identical blobs or trees are stored only once. This deduplication makes Git both space-efficient and self-verifying.
3. How a Commit Hooks Into History
Every commit object looks roughly like this:
tree
parent # absent for the very first commit
author
committer
Commit message explaining the snapshot…Git treats these commits as nodes in a Directed Acyclic Graph (DAG): each commit references its parent(s), forming a history chain (or multiple chains for merges).
4. References: Branches, Tags, and HEAD
-
Branches are simply files in
.git/refs/heads/containing a single commit SHA. -
Tags live in
.git/refs/tags/and point to commits (or annotated tag objects). -
HEAD is a special ref indicating your current checkout. It usually points to a branch ref (e.g.,
refs/heads/main) or directly to a commit (detached HEAD).
Changing branches (git checkout) means updating HEAD to point elsewhere, then rebuilding your Working Directory from the target commit’s tree.
5. The Index: Git’s Shopping Cart
Internally, the Index is a binary file .git/index that records:
-
File paths
-
Blob SHA references
-
File permissions and timestamps
When you git commit, Git takes the Index, writes a new tree object, then makes a commit object referencing that tree.
6. Storage on Disk: Loose Objects and Packfiles
-
Loose Objects: initially, each new blob/tree/commit is written as a compressed file under
.git/objects/xx/yyyy.... -
Packfiles: over time, Git consolidates loose objects into packfiles (
.git/objects/pack/pack-*.pack/.idx) using delta compression to save space and speed up network transfer.
git gc --auto (garbage collection) handles packing, pruning unreachable objects, and optimizing performance.
7. Core Operations Under the Hood
-
Commit
-
Write blobs for staged files.
-
Build trees recursively from directories.
-
Create commit object pointing to root tree and parent.
-
Update branch ref to new commit SHA.
-
-
Branch
- Create or move a ref file under
.git/refs/heads/.
- Create or move a ref file under
-
Merge
-
Find common ancestor commit.
-
Perform a three-way merge of trees.
-
Write new merge commit with two parents.
-
-
Rebase
- Replay commits onto a new base by rewriting commit objects with updated parent SHAs.
-
Checkout
-
Read target commit’s tree.
-
Overwrite Working Directory and Index to match.
-
Update HEAD to the target ref or commit SHA.
-
8. Why Git Is So Fast and Reliable
-
Data Integrity: SHA hashing ensures any corruption is detected.
-
Local-first: nearly all operations read/write locally-no network needed.
-
Immutable History: commits never change once created, making rollbacks trivial.
-
Delta Compression in Packs: efficient storage and transfer.
Conclusion
Understanding Git’s plumbing - its object model, references, and storage mechanisms-unlocks powerful workflows. You’re no longer just typing commands; you know what truly happens when you stage, commit, branch, or merge. Armed with this knowledge, you can diagnose low-level issues, craft advanced scripts, and leverage Git’s full potential in any development scenario.