Git95 min total · 17 parts
Git Internals and Workflows: Branching, Merging, and Rebasing
Part 2 of 17 · ~3 min
A Commit Is a Snapshot; a Branch Is Just a Pointer
Monday morning. Before writing a line of swap code, you cut a branch:
git switch -c feature/shift-swap
shiftplan is not a small repository — a few thousand files, several years of history — and that command finished before your finger left the Enter key. That is worth being curious about, because it tells you what a branch actually is.
Strip the word "branch" down to what it actually is: a label sitting on exactly one commit, free to be dragged onto a different one later. That is the entire definition. Creating one does not copy a file, duplicate history, or reserve space. It writes a name and a forty-character hash into a small file under .git/refs/heads/, and that is the whole operation. There is no per-branch storage anywhere, and any number of branch names can point at the same commit at the same time without conflicting.
So what is the thing being pointed at? Flip it around: a commit is a complete snapshot of every tracked file as of that moment, with a link back to whichever commit came right before it — two links, if it happens to be a merge commit. Not a diff. Git is happy to show you a commit as a diff, and keeps storage down by sharing identical file content between commits instead of copying it fresh each time, but what should sit in your head is "whole snapshot," because that is genuinely what is stored. It is why checking out any commit gives you the whole project at that moment and never requires replaying a stack of patches to get there.
One layer above that sits HEAD, doing the same job at a different altitude: HEAD is a pointer to the branch you currently have checked out. After that switch -c, the arrangement looks like this:
a4f1c0e ← main
↑
└──── feature/shift-swap ← HEAD
Three names, one commit. main and feature/shift-swap are both labels on a4f1c0e, and HEAD points at the label feature/shift-swap rather than at the commit directly.
Now you write the first piece of the feature and commit it:
git commit -m "Block swaps inside the deadline window"
Git builds a new commit object whose parent is a4f1c0e, and then does the one thing that makes "committing to a branch" work at all: it moves whichever branch HEAD points at forward onto the new commit.
a4f1c0e ← main
↓
7c1f4ae ← feature/shift-swap ← HEAD
main did not move, because HEAD was not pointing at it. That is the whole mechanism. Nothing about your commit is filed under "the shift-swap branch" — commits are shared, content-addressed objects sitting in one pile — and the only thing distinguishing your branch from main is which commit each label happens to name.
Once that clicks, a lot of Git stops being mysterious. Deleting a branch deletes a label, not commits. Two branches "having" the same commit is not duplication, it is two labels on one object. And a rebase, which we will get to on Wednesday, can produce commits that look identical to the ones you had while being genuinely different objects — because in Git, identity is the hash, and the hash covers the parent too.
You can watch the labels for yourself at any point:
git branch -v # local branches and the commit each one names
git branch -r # remote-tracking branches: where origin's labels were last seen
git log --oneline --graph --all # the whole shape, labels included