Git Internals: History as a Graph
Commits are snapshots linked by parents โ not diffs. Understanding the graph makes every Git command predictable.
You already use git commit daily. Now look at what it actually creates.
Commits are snapshots, not diffs
Each commit stores a full tree (snapshot) of every file, a message, an author, and a pointer to its parent commit(s). History is a directed graph:
A โ B โ C (main, linear)
\
D โ E (feature, diverged from B)
HEAD points to a branch; a branch is just a movable pointer to one commit. That is all a branch is โ 41 bytes in .git/refs.
Reading the graph
git log --oneline --graph --all
Learn to read this fluently. Questions professionals ask of history:
- Where did these two lines diverge?
git merge-base main feature - Which commits are on main but not here?
git log main ^feature(read: commits reachable from main, excluding feature) - What exactly changed in commit X?
git show X - When did this line last change?
git blame -L 10,20 fileโ andgit log -S "thatString"to find the commit that introduced it (pickaxe search).
Branch pointers move; commits are (mostly) forever
When you "delete" a commit from a branch, the commit object still exists โ the branch pointer simply stopped pointing at it. git reflog records every movement of HEAD for ~90 days, which is why almost nothing in Git is truly lost.
Three states, one mental model
- working directory โ your files right now
- staging area (index) โ the next snapshot, built with
git add - repository (HEAD) โ committed history
git diff (working vs index), git diff --staged (index vs HEAD), git diff main (working vs main). Professionals always check git status before any history-changing command.