Command Palette

Search for a command to run...

Hectal
PHASE 8Advanced ~7 min· topic 1 of 4

Topic 8.1

The Object Model: Blobs, Trees, Commits & Refs

In one line

Everything Git stores is one of four object types, named by the hash of its content. Branches and tags are just small files pointing at commits. Seeing this with plumbing commands makes Git fully explainable.

0/4 · 0%

Think of it like this

A library that files every page by a fingerprint of its text. Identical pages are stored once, any change produces a new fingerprint, and a 'book' (commit) is just a list of fingerprints plus a note saying which book came before it. A bookmark (branch) is a sticky note naming one book.

Key ideas

  1. 01

    BLOB: the contents of a file (no name, no permissions). TREE: a directory listing mapping names and modes to blobs and sub-trees. COMMIT: a pointer to one root tree, zero or more parent commits, author/committer, and message. Annotated TAG: a named, signed-able pointer to an object. Each object's ID is the hash of its content (SHA-1 today, SHA-256 supported), so identical content is stored once and history can't be altered silently.

  2. 02

    REFS are files (or entries in packed-refs) containing a commit hash: refs/heads/main, refs/tags/v1.2.0, refs/remotes/origin/main. HEAD usually contains ref: refs/heads/main (a symbolic ref); a 'detached HEAD' contains a hash directly. Creating a branch is writing a 41-byte file, which is why branches are cheap.

  3. 03

    A commit snapshots the whole tree, not a diff; diffs are computed when you ask. Unchanged files point to the same blobs, so snapshots are cheap. Packfiles (Topic 8.2) compress similar objects as deltas on disk.

  4. 04

    PLUMBING commands expose this: git cat-file -p <hash> (print an object), git ls-tree, git rev-parse main, git hash-object, git write-tree, git commit-tree. You won't use them daily, but they make everything else make sense.

Code & diagrams

a commit and what it points todiagram
Rendering diagram…
look inside with plumbingbash
git rev-parse HEAD                 # b7e1c0…
git cat-file -t HEAD               # commit
git cat-file -p HEAD               # tree 9c4d…  parent a3f0…  author …  message
git cat-file -p 'HEAD^{tree}'      # 100644 blob 5e1a…  README.md / 040000 tree …  src
cat .git/HEAD                      # ref: refs/heads/main
cat .git/refs/heads/main           # b7e1c0…   (or see .git/packed-refs)

Explain it without notes

01

Why are Git branches so cheap to create?

02

Why does changing one byte of an old commit change the IDs of every later commit?

Practice

01

Using only plumbing commands, show the content of README.md as it was three commits ago.

Done when you can

  • I can explain blobs, trees, commits, tags, and refs

  • I can inspect objects with cat-file and ls-tree