Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
General

How Git Actually Works Internally

An exploration of Git's internal architecture: content-addressable storage, object types, branches as pointers, and the reflog, with hands-on examples to demystify the version control system.

July 2026 11 min read 2 views 0 hearts

How Git Actually Works Internally: Beyond the Commands

Most developers use Git every single day. We git commit, git push, git merge, and move on. But have you ever paused to wonder what actually happens under the hood when you type those commands? I remember staring at a .git folder one afternoon and realizing I had no idea what any of those files meant. So let me walk you through what I discovered.

The Three Trees (Not a Forest)

Git internally operates with three main structures. Think of them as three separate snapshots of your project at any moment:

  1. The Working Directory — This is what you see in your file explorer or editor. Your actual files with all your changes.
  2. The Staging Area (Index) — Located in .git/index. This is where Git tracks what you plan to commit next.
  3. The Repository (Object Database) — Inside .git/objects. This holds all committed snapshots forever.

When you run git add, Git copies a snapshot of the file into the staging area. When you commit, Git takes that staging snapshot and stores it permanently in the object database. Simple enough, right?

The Real Magic: Content-Addressable Storage

Here is where things get fascinating. Git does not store files as files. Instead, it stores everything as objects keyed by a SHA-1 hash of their content.

Try this yourself: go to any Git repository and run:

git cat-file -p HEAD

You will see the tree object of your latest commit. That tree contains pointers to other trees and blobs (file content). Each blob is uniquely identified by its content hash. This means:

  • If two files have the same content, they share the same blob object.
  • If you rename a file without changing it, the blob does not change.
  • Git deduplicates storage automatically.

The Four Object Types You Never Knew About

Inside .git/objects, you will find:

Blobs

These are the actual file contents. A blob object stores just the file data, nothing else — no filename, no metadata, no permissions. Just bytes.

Trees

Trees are like directory listings. They map filenames to blob hashes (or other tree hashes for subdirectories). Each tree also stores file modes (like executable permissions).

Commits

A commit object contains: - A tree hash (the root of your project at that moment) - Parent commit hashes - Author and committer info - A timestamp - Your commit message

Tags

Tag objects point to a specific commit and include the tagger info and message.

How Git Actually Stores Your Data

When you run git add file.txt: 1. Git compresses the file using zlib. 2. It computes the SHA-1 hash of the content. 3. It stores the compressed blob in .git/objects/XX/YYYY... where XX is the first two characters of the hash, and YYYY... is the rest.

Try this experiment:

echo "hello world" | git hash-object --stdin -w

You will get a hash back, and a new file appears in .git/objects. That is your blob.

Branches Are Just Pointers

This blew my mind when I first learned it. A branch in Git is nothing but a file in .git/refs/heads/ containing a 40-character SHA hash of a commit. That is it.

When you switch branches, Git updates HEAD (a file in .git/HEAD) to point to a different branch file. The working directory gets updated to match the commit that branch points to.

The Reflog: Your Safety Net

Git keeps a local log of where HEAD has been in .git/logs/HEAD. This is called the reflog. If you accidentally reset or rebase and lose commits, you can recover them as long as they are in the reflog (usually 90 days for reachable commits).

Run git reflog next time you think you messed up. You will probably see your way back.

How Merges Actually Work

When you merge two branches: 1. Git finds the common ancestor commit (the merge base). 2. It computes the diff between that ancestor and each branch. 3. If the diffs do not conflict, Git applies both sets of changes. 4. It creates a new commit object with two parents.

If conflicts occur, Git inserts conflict markers into the working directory files and pauses. You resolve manually, stage the changes, then git commit.

Performance Tricks Git Uses

Git is surprisingly fast because: - Delta compression happens during packing (not during normal operations). Git stores full blobs individually, then periodically packs them into .pack files with delta chains. - Git uses a "pack bitmap" to quickly compute reachable objects during pushes and fetches. - Most operations are local — no network calls for diff, log, or status.

A Practical Example You Can Try

Create a new repo and track what happens:

mkdir gittest && cd gittest
git init
echo "test" > file.txt
git add file.txt

Now peek into .git/objects. You should see a directory with two hex characters and a file inside. That is your staged file.

Now commit:

git commit -m "first"

Check .git/refs/heads/master — it now contains the commit hash. Run git show HEAD to see the tree, and git cat-file -p <tree-hash> to see how the tree references the blob.

Why Understanding This Matters

When you know how Git stores data internally, debugging becomes easier: - Corrupted repo? You can manually inspect object files. - Large repository? You can find which blobs are taking space. - Lost commits? The reflog and object database can recover them.

More importantly, you stop treating Git as a black box. You start understanding why git rebase rewrites history (it creates new commit objects with new parents), why git push only sends new objects (Git compares SHA hashes), and why branching is so cheap (just creating a 41-byte file).

Next time you use Git, remember: you are not just running commands. You are interacting with a content-addressable filesystem that stores snapshots, not diffs. And that simple design choice is what makes Git so powerful.

Comments

Questions, corrections, and tips stay visible for everyone reading this page.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.