Git Internals
Also Known As
git object model
git DAG
git plumbing
TL;DR
Git stores all data as content-addressed objects (blobs, trees, commits, tags) in a directed acyclic graph — understanding this explains every git command's behaviour.
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
✗ Git stores file diffs — git stores complete snapshots of files (blobs) at each commit; deltas are only used in packfiles for storage efficiency.
Why It Matters
Understanding git's object model explains why rebase changes commit hashes, why force push is dangerous, and how to recover 'deleted' commits with reflog.
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
✗ Vulnerable
# 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>
✓ Fixed
# 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
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
23
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
No pings yesterday
Perplexity 6
Amazonbot 5
Google 4
Ahrefs 3
Majestic 1
ChatGPT 1
Also referenced
How they use it
crawler 19
crawler_json 1
Related categories
⚡
DEV INTEL
Tools & Severity
🔵 Info
⚙ Fix effort: Medium
⚡ Quick Fix
Understanding git objects (blob, tree, commit, tag) explains why git operations are fast — commits are just pointers to tree snapshots, not diffs; this explains why branches are cheap and merges are efficient
📦 Applies To
git
any
🔗 Prerequisites
🔍 Detection Hints
Confusion about why git is fast; misunderstanding of what a branch is; unexpected behaviour from reflog or object model
Auto-detectable:
✗ No
git
⚠ Related Problems
🤖 AI Agent
Confidence: Low
False Positives: High
✗ Manual fix
Fix: Medium
Context: File