C.W.K.
Stream
Lesson 01 of 05 · published

Branches Are Pointers

~18 min · branch, pointers

Level 0Untracked Rookie
0 XP0/47 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

A branch is a 41-byte file

The most important sentence in this whole quest: a branch in Git is a movable pointer to a commit. Not a copy. Not a folder. Not a snapshot. A 41-byte file containing one hash plus a newline. Creating a branch is one filesystem write. That single fact explains why Git encourages branching for everything — feature work, experiments, throwaway debugging, code review — and why teams that came from SVN are amazed by the speed.

Walk into .git/refs/heads/ and you will see this directly. Each filename is a branch name, each file holds the hash of the commit that branch currently points at. main, feature/login, chore/cleanup — they are siblings in a directory. There is no "main is special" magic; convention designates main as the integration branch, and tooling enforces it, but the data shape is identical.

What the pointer points at is the tip of that branch. Walking from the tip backwards via parent pointers gives you the branch's history. Two branches that share old commits both reach the shared commits when walked back. This is how Git computes "what is on feature but not on main" — set difference on reachable commits, no copying involved.

The implications run far. Renaming a branch is renaming the file. Deleting a branch is removing the file (the commits stay, orphaned, until garbage collected). Switching branches updates HEAD to point at a different ref and updates the working tree to match the new tip. Once you see branches as pointers, the rest of branching stops feeling magical and starts feeling like file operations.

Code

Branches are files. See for yourself.·bash
ls .git/refs/heads/
# main
# feature/login
# chore/cleanup

cat .git/refs/heads/main
# a1b2c3d4e5f6...    (one commit hash + newline = 41 bytes)

# Plumbing equivalent that walks packed refs too:
git for-each-ref --format='%(refname:short) -> %(objectname:short)'
Create, rename, delete — all pointer ops·bash
# Create a branch at HEAD (does NOT switch)
git branch feature/profile

# Create at a specific commit:
git branch feature/profile abc1234

# Rename current branch:
git branch -m new-name

# Delete (only if merged into upstream):
git branch -d feature/profile

# Force-delete (commits become orphaned):
git branch -D feature/profile

External links

Exercise

In a scratch repo, run ls .git/refs/heads/ and cat .git/refs/heads/main. Create three branches with git branch. Verify each one is now a file. Move one branch to a different commit by hand: git update-ref refs/heads/<name> <other-hash>. Confirm with git log that the branch now points where you said. Note in writing what surprised you about the file-level view.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.