The Immutable Object Model

Life as a Git repositoryintermediate · standard · comprehensive | model: claude-opus-4-8 | 2026-06-19
Quick ref
git cat-file -p <oid> print any object
git rev-parse HEAD resolve ref to OID
git reflog find lost commits
git for-each-ref list all refs
git fsck --lost-found recover dangling objects
git push origin HEAD:branch move a remote ref

The Immutable Object Model

Git is a content-addressable store: four object types keyed by the SHA-1/SHA-256 hash of their contents. Identical content yields identical OIDs; changing anything mints a new object.

ObjectContainsPoints to
blobraw file bytes (no name)nothing
treenames, modes, OIDsblobs & subtrees
committree, parents, author, messageone tree + parent commits
tagtarget OID, tagger, messageany object (annotated tags)
Note Commits form a DAG via parent links; a merge commit has two or more parents. A branch is just a moving pointer to a commit; "history" is everything reachable from it.

Plumbing Beneath the Porcelain

git hash-object -w file
Hash content and write a loose blob into the object store.
git cat-file -t|-s|-p <oid>
Show an object's type, size, or pretty-printed content.
git update-index --add file
Stage content into the index (the proposed next tree).
git write-tree
Snapshot the index into a tree object, returning its OID.
git commit-tree <tree> -p <parent>
Wrap a tree in a commit; the raw building block of git commit.
git update-ref refs/heads/x <oid>
Move a ref to a commit — separate step from creating the object.
Tip Porcelain = plumbing pipeline: commitwrite-treecommit-treeupdate-ref. Knowing this makes recovery and scripting trivial.

Refs, HEAD & Reflogs

Ref anatomy

Refs are files under .git/refs/ (or packed in packed-refs) holding an OID. HEAD is a symbolic ref pointing at the current branch; detached HEAD points straight at a commit.

The reflog

Every ref movement is logged locally in .git/logs/. HEAD@{2} or main@{yesterday} reaches prior positions — your undo history and primary recovery tool.

git symbolic-ref HEAD
Show which branch HEAD currently follows.
git for-each-ref --sort=-committerdate
Enumerate refs with custom formatting and ordering.
git reflog expire --expire=now --all
Drop reflog entries — accelerates "forgetting" before gc.
git pack-refs --all
Collapse loose refs into packed-refs.

Working Tree, Index & State Movement

Three trees: the working tree (files on disk), the index (staging area), and HEAD (last commit). Commands differ in which they touch.

CommandMoves HEADTouches index / worktree
git reset --softyesneither
git reset --mixedyesindex only (default)
git reset --hardyesindex + worktree
git restore --staged fnoindex only
git restore fnoworktree only
git switch <branch>moves HEAD refupdates worktree
git switch -c feature
Create and check out a branch (modern checkout -b).
git stash push -m "wip"
Park dirty changes as commits under refs/stash.
git clean -fdx
Delete untracked files/dirs, including ignored ones — irreversible.
Warning reset --hard and clean destroy uncommitted work that was never an object — the reflog cannot save what was never committed.

Revision Selection, Pathspecs & Attributes

HEAD~3 / HEAD^2
First-parent ancestor / second parent of a merge.
main..feature
Commits reachable from feature but not main.
main...feature
Symmetric difference; with --left-right shows sides.
:(exclude)*.test.js
Magic pathspec to exclude paths from an operation.
.gitignore / .gitattributes
Per-path ignore rules and behaviors (eol, diff, filter, merge).
git check-ignore -v file
Show which ignore rule matched a path.

Integration: Merge, Rebase & Conflicts

Integration is separate from transport — these only rearrange the local DAG. Rewriting always mints new commits; originals linger until gc