Back to News & Insights
DevOps October 10, 2026 · 11 min read

Git Isn't a Diff Tracker: How Blobs, Trees, DAG Commits, and the Index Actually Work Under the Hood

A visual, 10-minute deep dive into Git internal architecture. Learn how content-addressed storage works, why Git never stores diffs, how the index prepares tree objects, and how to recover any lost commit using the reflog.

Git Isn't a Diff Tracker: How Blobs, Trees, DAG Commits, and the Index Actually Work Under the Hood

"Git tracks changes. When you edit a file and commit, Git calculates the diff between the old file and the new file and saves the patch."

It is a completely reasonable mental model. After all, when you run git diff or git show, the terminal prints green additions and red deletions. Older version control systems like CVS and Subversion (SVN) worked exactly that way: they stored a base file and appended delta patches across time.

Git does not track file diffs. Git does not store patches. Git does not even have an internal concept of "file renames".

Underneath its porcelain command line interface, Git is something radically simpler and far more elegant: an immutable, content-addressed key-value object store sitting underneath a Directed Acyclic Graph (DAG) of snapshot trees.

When developers treat Git as a magical incantation machine, commands like git rebase, git reset --mixed, or a detached HEAD state feel like minefields. But the moment you look inside the .git folder and understand how Git represents data, the mystery dissolves.

Here is what actually happens under the hood when you use Git. Peeking Inside .git: The Content-Addressed Object Store

When you type git init in an empty folder, Git does not set up a server or connect to a daemon. It creates a single hidden directory named .git.

This folder is Git's database. Every piece of data in your project, every file, every directory listing, every commit message, and every tag, is stored here as one of four fundamental object types: Blob: Stores raw file contents (uncompressed byte streams). It does not store file names, paths, or file permissions. Tree: Represents a directory. It maps file names and file permissions to the cryptographic hashes of blobs and child trees. Commit: A snapshot pointer. It references a top-level root tree, zero or more parent commit hashes, an author, a committer, and a commit message. Annotated Tag: A permanent pointer to a specific commit, containing a tagger name, date, and verification message.

Git identifies every object by its cryptographic hash. In standard Git, this is a 40-character hexadecimal SHA-1 string (newer versions can also use SHA-256).

If you create a file with the content hello world\n and pass it to Git's low-level hash calculation tool:

Git prepends a standardized header to the raw data: the object type (blob), a space, the content length in bytes, and a null byte (\0). Then it passes the concatenated buffer through the SHA algorithm:

If you name that file README.md, main.py, or config.json, the SHA hash is identical. If five different directories in your project contain an identical file, Git stores that blob exactly once.

Git takes the first two characters of the 40-character hash (3b) and creates a subfolder. The remaining 38 characters become the filename. This split prevents operating systems from choking when thousands of objects accumulate in a single directory.

The file on disk is compressed using zlib. You can inspect its contents and type at any time using Git's inspection tool, git cat-file: The Snapshot Architecture: Why Git Never Stores Diffs

Because older version control tools stored delta diffs, many developers assume Git calculates differences when saving new commits.

When you commit a change, Git creates a new Tree object representing your root folder. That Tree object contains a complete manifest of every file and folder in the project.

You might wonder: If Git stores full snapshots rather than diffs, why doesn't my repository size explode into gigabytes after twenty commits?

Suppose your repository contains 1,000 files across 20 folders. You open docs/guide.md, fix a single typo, and run git commit.

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation