By admin , 29 April 2026

Four object types

Git stores everything as content-addressable objects under .git/objects. There are four types: blob (file contents), tree (directory listing of blobs and subtrees), commit (snapshot pointer with author, committer, message, and parents), and tag (annotated tag with signer and message). Each is named by the SHA-1 (or SHA-256) of its content.

Inspecting

git cat-file -t <sha>        # type
git cat-file -p <sha>        # pretty-print
git cat-file -s <sha>        # size
git ls-tree HEAD             # list tree contents
git rev-parse HEAD^{tree}    # tree of HEAD

Loose vs packed

Newly created objects start as loose: one zlib-compressed file per object under .git/objects/xx/yyyy.... Garbage collection later combines many objects into a packfile under .git/objects/pack/, sharing common bytes via delta compression. See "Git internals: packfiles and delta compression".

Hashing

Compute an object hash without writing it:

echo "hello" | git hash-object --stdin
git hash-object -w README.md       # write to object DB

Trees encode permissions

A tree entry is mode + name + sha. Modes are 040000 (directory), 100644 (regular), 100755 (executable), 120000 (symlink), 160000 (gitlink/submodule). Git does not store other Unix permissions.

Walking history

git log --raw                # show changed blobs
git log --pretty=raw         # show internal commit format
git rev-list --objects HEAD  # commits + reachable trees + blobs

rev-list --objects is what git fsck and git pack-objects use under the hood.

Reachability and pruning

An object is reachable if some ref (branch, tag, reflog entry) leads to it through the commit-tree-blob graph. Unreachable objects are pruned by gc after the reflog expiry window (default 90 days for reachable, 30 for unreachable).

git fsck --unreachable
git gc --prune=now

SHA-256 transition

Modern Git supports SHA-256 repositories (git init --object-format=sha256). Interop with SHA-1 repos remains limited; choose carefully for new projects expecting decades of life.

Common mistakes

Editing files under .git/objects directly. Don't. Use plumbing commands like git hash-object and git update-ref. Assuming SHA-1 collisions are impossible — Git includes hardened collision detection (SHAttered) by default. Confusing tree SHA with commit SHA in scripts; HEAD alone resolves to a commit, HEAD^{tree} to its tree.

Related

See "Git internals: packfiles and delta compression", "Git internals: references and the reflog", and "Git internals: the index format".