Do we think of Git commits as diffs, snapshots, and/or histories?

Whether Git commits should be understood as diffs, snapshots, or full histories turns out to shape how people learn, teach, and safely use Git. Commenters contrast Git’s actual storage model (content-addressed snapshots in a DAG, with delta compression as an implementation detail) with how core commands behave, noting that many operations (rebase, cherry-pick, merge) conceptually treat commits as changes between snapshots. A recurring theme is that simplistic or misleading mental models—especially “commits are diffs”—can make advanced workflows and conflict resolution harder to reason about, so choosing and explaining abstractions carefully is seen as crucial for developer productivity.

Mental models: diffs, snapshots, histories

  • Many argue commits are conceptually snapshots: a full repo state (tree) plus parent pointers, forming a DAG.
  • Others instinctively think of commits as diffs/changes, because they author “a change” and tools like git show, rebase, cherry-pick, and reviews all present or operate on diffs.
  • “History” is described as a commit plus all its ancestors (what other systems call a branch); some find “history vs snapshot” a confusing distinction since each snapshot links into that history.
  • Several suggest a dual (or triple) view: commits as snapshots, diffs, and parts of history, with the “right” model depending on the operation.

Implementation vs abstraction

  • Strong disagreement over whether “how git implements it” is a good teaching model.
  • One side: commits-as-snapshots and the object store (trees, blobs, content addressing) are essential for developers to avoid confusion in merges/rebases.
  • Other side: implementation (including packfiles and delta compression) is an optimization and often distracts beginners; the UI is about states over time, with diffs derived on demand.
  • Broader debate uses a gas-pedal analogy: some emphasize intuitive abstractions, others argue that leaky abstractions and debugging needs make real implementation knowledge valuable.

Rebases, merges, and the DAG

  • Rebase is described as “reset to a new base + cherry-pick each commit,” conceptually applying per-commit diffs via 3‑way merges.
  • Several note that thinking purely in diffs during rebases causes confusion, especially when commit order changes or when merge commits are involved.
  • Merge commits can introduce arbitrary new changes (including from conflict resolution) and can break working parents; “merge history = safe history” is flagged as unsafe.

Storage and performance

  • Clarification that git’s logical model is snapshots; physical storage may use delta compression (“deltas”) inside packfiles, but that is invisible to users.
  • Explanations detail copy‑on‑write trees, heavy deduplication via hashes, and why this stays fast and space‑efficient even with many commits.
  • Some argue that calling commits “diffs” because of packfile deltas is misleading; others think it’s acceptable if “diff” is loosely defined.

Teaching, usability, and other tools

  • Several say the “diff mental model” is the main source of everyday confusion and advocate always teaching snapshots first.
  • Others report long‑term success thinking in diffs, claiming they rarely need the snapshot model explicitly.
  • Git’s UI and terminology are widely criticized as confusing and tied too closely to internals; Mercurial is frequently cited as having a cleaner, more user‑friendly model (though now niche).

Diffs and their non-uniqueness

  • Commenters stress that there is no single canonical diff: algorithms and options (--word-diff, patience, histogram, language-aware hunks) change what users see.
  • This can mismatch how authors conceptualize their edits, but most accept “a diff, not the diff” for practical use.