Command Palette

Search for a command to run...

Hectal
PHASE 0Beginner ~14 min· topic 5 of 5

Topic 0.5

The Commit Graph: SHAs, Parents, and HEAD

In one line

Every commit points to its parent, forming a chain (or graph) of history — and SHAs, HEAD, and this parent-pointer structure are the foundation that branching, merging, and rebasing all sit on top of.

0/5 · 0%

Think of it like this

A chain of paper receipts, each one stapled to the receipt that came right before it — to find out the full history, you just follow the staples backward, one at a time. A Git commit works the same way: each one points to exactly the commit that came before it (its PARENT), and following those pointers backward IS the project's history.

Key ideas

  1. 01

    Every commit is identified by a SHA — a long hexadecimal hash (like a3f5c9e...) computed from the commit's actual content: the files it changed, its message, its author, and its parent's SHA. This means the SHA isn't an arbitrary counter — it's a genuine fingerprint, and changing ANYTHING about a commit (even just its message) produces a completely different SHA.

  2. 02

    Most commits have exactly ONE parent (the commit right before them) — but a MERGE commit (Phase 2) has TWO parents, since it's the point where two separate lines of history come together. This is exactly why Git history is technically a GRAPH, not a simple straight line, once branching and merging are involved.

  3. 03

    HEAD is a special pointer that always represents 'where you currently are' — normally, HEAD points to the tip of whichever branch you have checked out, and moves forward automatically every time you make a new commit. Understanding that HEAD is just a pointer, not a fixed location, is essential background for Phase 2's branching and Phase 5's history rewriting.

  4. 04

    You rarely need to type a full 40-character SHA — Git accepts a SHORT, unique PREFIX (commonly 7 characters, like a3f5c9e) anywhere a full SHA is expected, and git log --oneline shows exactly this short form by convention, since it's plenty unique for any reasonably sized project.

  5. 05

    git show <sha> displays the full details of any specific commit — its message, author, and the exact diff it introduced — genuinely useful for inspecting any single commit in isolation, whether it's the most recent one or one from months ago, once you have its SHA (from git log, git blame, or anywhere else Git shows one).

Code & diagrams

CommitGraphdiagram

A simple linear history — each commit's arrow points back to its one parent. HEAD tracks the tip.

Rendering diagram…
commit-graph.shmarkdown

See the actual SHAs, parents, and HEAD pointer in a real repo.

cd ~/scratch/my-first-repo

# See full SHAs and every detail
git log

# See short SHAs, one line each — the everyday view
git log --oneline

# Inspect exactly one commit
git show --stat HEAD
# HEAD always refers to your current position — try it directly

# See where HEAD actually points right now
cat .git/HEAD
# ref: refs/heads/main  — HEAD is pointing at the "main" branch, not a commit directly

# A commit's SHA changes if ANYTHING about it changes — proof:
git commit --allow-empty -m "test commit"
git log -1 --format="%H"
git commit --amend -m "test commit (edited)"
git log -1 --format="%H"
# a completely different SHA, even though only the message changed

Explain it without notes

01

Why is a commit's SHA computed from its content, rather than just being an incrementing number like row 1, row 2, row 3?

02

What's the actual difference between a normal commit and a merge commit, in terms of parents?

Practice

01

In any repo with a few commits, run git log --oneline and identify the short SHA of each commit, then use git show on one of them to see its full diff.

02

Make an empty commit, note its SHA with git log -1 --format="%H", amend just its message, and confirm the SHA changed completely even though nothing else did.

Trade-offs

  • ↔

    Content-addressed SHAs make history verifiably trustworthy and enable Git's whole distributed model, but they're genuinely unfriendly for humans to work with directly compared to a simple incrementing number — this is exactly why tags (Phase 6) and branch names exist: human-friendly, movable labels pointing AT a specific SHA, so people rarely need to type or remember one directly.

Done when you can

  • I understand that a commit's SHA is a content-based fingerprint, not an arbitrary ID.

  • I can explain the difference between a normal commit (one parent) and a merge commit (two parents).

  • I understand that HEAD is a pointer to 'where I currently am,' not a fixed commit.