Git Internals
debt(d9/e7/b5/t7)
Closest to 'silent in production until users hit it' (d9). The detection_hints explicitly state 'automated: no' and the only tool listed is git itself (plumbing commands). Misunderstandings about the object model surface only when developers encounter unexpected behaviour — force-push disasters, lost-looking commits, confusing rebase results — all of which are silent until the moment of impact in production workflows.
Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix is conceptual, not a one-line patch — it requires re-educating developers and potentially revisiting branching strategies, rebase vs merge policies, and CI/CD pipeline assumptions. Misunderstandings rooted in wrong mental models (diffs vs snapshots, branch deletion, merge parents) require updating practices across a team and codebase workflow, not just a single file change.
Closest to 'persistent productivity tax' (b5). Applies to 'any' context per applies_to, meaning every developer on every project using git carries this conceptual load. However, it doesn't fully define system shape (b7/b9) — it's a persistent tax on debugging, onboarding, and workflow decisions rather than an architectural constraint that shapes every change.
Closest to 'serious trap (contradicts how a similar concept works elsewhere)' (t7). The canonical misconception — 'Git stores file diffs' — is directly contradicted by how most other VCS tools (SVN, CVS) actually work, making the wrong assumption feel natural to developers migrating from those systems. The common_mistakes reinforce this: branch deletion not deleting commits, and merge commit dual-parent behaviour, are all non-obvious traps that contradict intuitive expectations.
Also Known As
TL;DR
Explanation
Git's object model: blobs store file content, trees store directory listings, commits point to a tree plus parent commits and metadata, tags point to commits. Every object is named by the SHA-1 hash of its content. Branches and tags are simply pointers (refs) to commit hashes. HEAD points to the current branch or commit. This model explains why branches are cheap (just a file with a hash), why git is fast (content addressing), and why history rewriting changes hashes.
Diagram
flowchart TD
subgraph Git Objects
BLOB[Blob<br/>file content]
TREE[Tree<br/>directory listing]
COMMIT[Commit<br/>tree + parent + message]
TAG[Tag<br/>points to commit]
end
COMMIT -->|points to| TREE
TREE -->|contains| BLOB
TREE -->|contains| TREE2[Subtree]
COMMIT -->|parent| PREV[Previous commit]
subgraph Refs
HEAD[HEAD] -->|points to| BRANCH[branch name]
BRANCH -->|points to| COMMIT
end
INFO[Everything is content-addressed<br/>SHA-1 hash of contents<br/>immutable once written]
style COMMIT fill:#6e40c9,color:#fff
style TREE fill:#1f6feb,color:#fff
style BLOB fill:#238636,color:#fff
style INFO fill:#d29922,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Thinking git stores diffs — it stores full snapshots; packfiles compress them later.
- Not understanding that branch deletion does not delete commits — unreferenced commits are garbage collected eventually.
- Not using git cat-file to inspect objects when debugging — the plumbing commands reveal what high-level commands hide.
- Not understanding that a merge commit has two parents — this is what makes merge vs rebase history different.
Code Examples
# Losing work by assuming branch deletion removes commits:
git branch -D feature/experiment
# The commits still exist! They are just unreferenced.
# Recover with: git reflog | grep 'feature/experiment'
# git checkout -b recovered <hash>
# Inspect git objects directly:
git cat-file -t HEAD # Shows type: commit
git cat-file -p HEAD # Shows: tree, parent, author, message
git cat-file -p HEAD^{tree} # Shows directory listing
git log --graph --oneline --all # Visualise the DAG