Every object Git stores lives under .git/objects/, addressed by the SHA-1 hash of its content.
The path is split: .git/objects/ab/c123… where ab is the first 2 chars and c123… is the rest. Why? Filesystems struggle with directories containing millions of entries — Git scales by splitting into 256 sub-buckets.
Four object types:
- blob — raw file content
- tree — directory listing (filename → mode → blob/tree hash)
- commit — pointer to a tree + parents + metadata
- tag (annotated) — pointer to another object + message
All stored zlib-compressed. Inspect any:
git cat-file -t <hash> # type
git cat-file -p <hash> # pretty-printed contents
git cat-file -s <hash> # size in bytes
Two identical files anywhere in history share one blob — content-addressed dedup is automatic.