Git Internals — How Git Really Works
BeginnerGit stores everything as four object types in a content-addressable store: blobs (file content), trees (directories), commits (snapshots), and tags. Every object is identified by its SHA-1 hash.
Overview
Most developers use Git for years without understanding its internals, then hit a confusing situation (detached HEAD, lost commit, weird merge) and have no mental model to reason from. Git's storage model is elegant: it is a key-value store where the key is a SHA-1 hash of the content and the value is the object itself. This means identical content is stored once, history is tamper-evident (changing any byte changes the hash), and every object is self-verifying. Once you understand blobs, trees, commits, and refs, every Git command makes intuitive sense.
The Four Object Types
Git has exactly four object types. A blob stores raw file content (no name, no permissions). A tree stores a directory listing — names, permissions, and pointers to blobs or other trees. A commit stores a pointer to a root tree, parent commit(s), author info, timestamp, and your message. A tag is a named pointer to any object (usually a commit).
// Look inside Git's object store
ls .git/objects/
# 4a/ 9c/ f2/ info/ pack/
# See the type and content of any object by its hash
git cat-file -t 4a7f3b2c # → blob
git cat-file -p 4a7f3b2c # → "function login() { ... }"
git cat-file -t 9c2d8e1f # → tree
git cat-file -p 9c2d8e1f
# 100644 blob 4a7f3b2c auth.js
# 100644 blob 7e9f1a0b index.js
# 040000 tree 2b4c8d6e components/
git cat-file -t f2a1c9b3 # → commit
git cat-file -p f2a1c9b3
# tree 9c2d8e1f
# parent 3a5b2c1d
# author Akshay <a@example.com> 1704067200 +0530
# committer Akshay <a@example.com> 1704067200 +0530
#
# Add login validationThe Commit DAG
Commits form a Directed Acyclic Graph (DAG) — each commit points to its parent(s). Branches are just named pointers (refs) to commits. HEAD is a pointer to the currently checked-out branch or commit. This is why branching in Git is free — creating a branch just writes a 41-byte file.
// Git commit history as a DAG
//
// HEAD
// │
// main branch feature branch
// │ │
// â–¼ â–¼
// ┌─────────┠┌─────────â”
// │ commit │◄──────────│ commit │
// │ a3f8c12 │ │ 7b2e441 │
// â””────┬────┘ â””────┬────┘
// │ │
// ▼ │
// ┌─────────┠│
// │ commit │◄──────────────┘
// │ 9d2e441 │ (common ancestor)
// â””────┬────┘
// │
// â–¼
// ┌─────────â”
// │ commit │
// │ 1a2b3c4 │ (initial commit, no parent)
// â””─────────┘
# A branch is just a file containing a commit hash:
cat .git/refs/heads/main
# → a3f8c12e9d2e441...
# HEAD points to the current branch:
cat .git/HEAD
# → ref: refs/heads/mainContent-Addressable Storage
Git uses SHA-1 (transitioning to SHA-256) to hash every object. The same content always produces the same hash — identical files across branches are stored once. This also means you cannot change history without changing all subsequent hashes, making Git history tamper-evident.
# Git hashes are deterministic — same content, same hash
echo "hello world" | git hash-object --stdin
# → 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
# (always the same hash for "hello world
", on any machine)
# This is why "git gc" can deduplicate objects:
# Two branches with the same file share one blob object
# Verify an object hasn't been corrupted:
git fsck --full
# SHA-1 collision resistance means:
# If someone tampers with a commit, its hash changes,
# which changes all child commit hashes → immediately detectableKey Points to Remember
- 1Four object types: blob (file content), tree (directory), commit (snapshot + metadata), tag (named pointer)
- 2Every object is identified by SHA-1 hash of its content — same content = same hash, stored once
- 3Commits form a DAG — each commit points to parent(s), never backward
- 4Branches and HEAD are just files containing a 40-character SHA-1 hash — that's why branching is instant
- 5git cat-file -t <hash> and git cat-file -p <hash> let you inspect any object directly
Interview Questions
Sign in to ask AriaWhat are the four object types in Git? What does each store?
What is a Git branch internally? Why is creating a branch in Git "cheap"?
What is the difference between HEAD and a branch?
What does "detached HEAD" mean and how does it happen?
Ask Aria about Git Internals — How Git Really Works
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.