Git Internals
Courses 1 and 2 covered git at the command level — what to type, what happens. This chapter goes one layer deeper: what's actually stored inside .git, and how. Understanding this isn't required to use git well day to day, but it's exactly what turns "I memorised these commands" into "I understand why these commands work," and it's the foundation everything else in this advanced course builds on — interactive rebase, reflog recovery, and real submodules all make far more sense once the object model clicks.
Git Is a Content-Addressable Object Database
Strip away every porcelain command (commit, branch, merge) and underneath, git is fundamentally a simple key-value store: content goes in, a hash comes out, and that hash is forever the key to retrieve that exact content. This is what "content-addressable" means — the address is a hash of the content itself.
Seeing this for real
$ git cat-file -t HEAD
commit
$ # Show a commit object's raw content
$ git cat-file -p HEAD
tree 9f8e7d6c5b4a...
parent a1b2c3d4e5f6...
author Philip Osztromok <you@example.com> 1750000000 +0100
committer Philip Osztromok <you@example.com> 1750000000 +0100
Fix login validation bug
Refs — Human-Readable Names for Hashes
Nobody wants to type 40-character hashes constantly. A ref is simply a small file containing a hash, with a memorable name — this is the literal mechanism behind everything Course 1, Chapter 4 explained conceptually about branches being "just a movable label."
├── refs/
│ ├── heads/
│ │ ├── main ← contains just a commit hash, nothing more
│ │ └── feature/login
│ └── tags/
│ └── v1.2.0
├── HEAD ← usually contains "ref: refs/heads/main", a pointer to a pointer
└── objects/ ← every blob, tree, commit, and tag object, content-addressed
$ cat .git/HEAD
ref: refs/heads/main
$ # And what that ref points to
$ cat .git/refs/heads/main
a1b2c3d4e5f6789...
This is the literal, file-level answer to "what is HEAD" from Course 1, Chapter 4 — it's a text file containing either a ref name (the normal case) or, occasionally, a raw commit hash directly (a "detached HEAD" state).
Where Everything Else from Courses 1 and 2 Fits
- git commit creates a new commit object, pointing at a new tree object built from your staged blobs, then moves the current branch's ref file to point at it.
- git branch <name> just creates a new file in
.git/refs/heads/containing the current commit's hash. - git merge creates a commit object with two parent hashes instead of one.
- git rebase (Course 2, Ch2) creates brand-new commit objects with different hashes, then moves the branch ref to point at the new chain — this is the literal mechanism behind "rebase rewrites history."
- The broken gitlink incident (Course 1 Ch9, Course 2 Ch10) — a gitlink is a special tree entry (mode
160000) that records a commit hash from a different object database entirely, rather than a blob or tree from this one. When that other database (the nested .git) disappears, the reference becomes unresolvable.
.git/ is how repositories get genuinely, sometimes unrecoverably, broken — every porcelain command (commit, branch, merge, rebase) exists specifically to make these changes safely and consistently. Use git cat-file, cat .git/HEAD, and similar read-only exploration to build understanding, never to modify.
Command Reference
| Command | What it does |
|---|---|
| git cat-file -t <hash> | Shows the object type (blob, tree, commit, tag) for a given hash |
| git cat-file -p <hash> | Pretty-prints the object's actual content |
| git ls-files -s | Shows tracked files with their mode and blob hash (used in Course 1/2's gitlink diagnosis) |
| cat .git/HEAD | Shows what HEAD currently points to — a ref name, or a raw hash if detached |
| cat .git/refs/heads/<branch> | Shows the exact commit hash a branch currently points to |
Chapter 1 Quick Reference
- Git is content-addressable — every object's hash is a function of its own content
- Four object types: blob (file content), tree (directory listing), commit (snapshot + metadata), tag (annotated marker)
- A ref is just a small file holding a hash with a memorable name — the literal mechanism behind branches
- HEAD is a file, usually containing "ref: refs/heads/<branch>" — a pointer to a pointer
- git cat-file -p / -t — read-only tools for exploring objects directly
- Never hand-edit files inside .git/ — porcelain commands exist to do this safely
- Next chapter: interactive rebase — squashing, reordering, and splitting commits safely