Concept · How Git works
Git’s object model
Blobs, trees and commits, each named by the hash of its content — a snapshot store, not a diff store.
3 minblobtree objectcommit objectcontent-addressable storage
Underneath every Git command is a simple content-addressed store. Every object is saved under the hash of its own content, SHA-1 by default with SHA-256 available, in .git/objects. There are three object types that matter day to day.
| Object | Holds | Points to |
|---|---|---|
| Blob | A file's contents (no name, no permissions) | Nothing |
| Tree | A directory listing: names, modes and the hash of each entry | Blobs and other trees |
| Commit | Author, committer, date, message | One root tree, and zero or more parent commits |
commit 9f2c… "Add login form"
├─ parent → commit 41ab…
└─ tree 7d10…
├─ README.md → blob e69d…
└─ src/ → tree 3c4a…
└─ login.ts → blob b81f…git cat-file -p HEAD # show the commit object
git cat-file -p HEAD^{tree} # show its treeSnapshots, not diffs
A commit records the entire project state through its tree, not a list of changes. When you run git diff or git show, Git computes the difference between two snapshots on the fly. This is efficient because:
- Unchanged files and folders are shared. If only
login.tschanged, the new commit's tree reuses the old blob and tree hashes for everything else. Only the changed blob and the trees above it are new. - Identical content is stored once, wherever and however often it appears.
- Packfiles compress similar objects against each other on disk, so storage is still compact.
Why hashes matter
- Integrity. A commit's hash covers its tree, which covers every file, plus its parents' hashes, which cover the whole history. Change one byte anywhere in the past and every hash after it changes. This is a Merkle tree, the same structure that lets replicas find their differences quickly.
- Immutability. Objects can't be edited, only replaced. "Amending" or "rebasing" a commit creates new commits with new hashes. That's why rewriting shared history causes trouble. See merge vs rebase.
- Cheap comparison. Two trees with the same hash are identical, so Git can skip whole directories when diffing or merging.
Branches and tags aren't objects at all. They're small files that name a commit hash. See refs and HEAD.