Git Internals
What this module covers
Blob, tree, commit, and annotated tag objects Content-addressed object storage The index/staging area HEAD, branches, refs, and symbolic refs Commit ancestry and DAGs
Loose objects, packfiles, and garbage collection Reflog and unreachable objects Plumbing versus porcelain commands
git cat-file, git ls-tree, and git rev-parse How Git calculates diffs and merges conceptually
11.1 The object model
Git primarily stores:
Blob: file content.
Tree: directory-like structure mapping names to objects and modes.
Commit: snapshot root plus parent commit(s), author/committer metadata, and message.
Tag object: optional annotated-tag metadata pointing to an object.
Git object IDs are hashes of object content and type/size framing. Hash algorithms and repository format details depend on repository configuration and Git version; avoid hard-coding assumptions about object-ID length.
Text equivalent: a tag points to a commit; each commit points to one root tree and to its parent commits; trees map names to blobs (file contents) and to other trees (subdirectories). Identical content is stored once, because its ID is a hash of the content.
flowchart TD
TAG[Annotated tag v1.2.0] --> C2[Commit]
C2 -->|parent| C1[Commit]
C2 --> T2[Tree: root]
T2 --> B1[Blob: README.md]
T2 --> T3[Tree: src]
T3 --> B2[Blob: parse.c]11.2 Inspecting objects
Terminal session (Git 2.34.1, Ubuntu 22.04 on WSL2; the same practice repository throughout the Git modules, with identity Example Developer and commit dates fixed to 1 January 2026 so the IDs are reproducible), with path/to/file as README.md:
These commands inspect repository objects and tree entries. git cat-file -p is especially useful for learning how commits and trees refer to one another.
An object ID is a hash you can compute yourself Terminal session (Git 2.34.1) in the same repository:
A blob's ID is the SHA-1 of the header blob <size>\0 followed by the content — git hash-object and a plain sha1sum agree. (Repositories can also use SHA-256 object format.)
git rev-parse HEAD
git cat-file -t HEAD
git cat-file -p HEAD
git ls-tree HEAD
git show HEAD:path/to/file$ git rev-parse HEAD
928632399905e96799eaabe7c41cef94b9cf64a8
$ git cat-file -t HEAD
commit
$ git cat-file -p HEAD
tree 4e3fd468f0119244ce57143faf17f6d451c86f86
parent 12ae10387ed14999fa71d46bcee06dc531fa4e6e
author Example Developer <[email protected]> 1767226920 +0000
committer Example Developer <[email protected]> 1767226920 +0000
fix: reject NULL input in parser
$ git ls-tree HEAD
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 .env.example
100755 blob 78efc4ff3d2218481549c1118b59ce21a70f11fd .gitignore
100644 blob dfd2cb6407735547d4995f61aeefc201e5f59521 README.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 notes.md
040000 tree 3415c421917d1602b6de44a8b25c73f2befd082b src
$ git show HEAD:README.md
# Sensor Demo
Reads a sensor and reports scaled values.$ printf 'hello\n' | git hash-object --stdin
ce013625030ba8dba906f756967f9e9ca394464a
$ printf 'blob 6\0hello\n' | sha1sum
ce013625030ba8dba906f756967f9e9ca394464a -
$ git cat-file -p "HEAD^{tree}"
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 .env.example
100755 blob 78efc4ff3d2218481549c1118b59ce21a70f11fd .gitignore
100644 blob dfd2cb6407735547d4995f61aeefc201e5f59521 README.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 notes.md
040000 tree 3415c421917d1602b6de44a8b25c73f2befd082b src
$ git count-objects -v | head -2
count: 82
size: 328gitobjects11.3 Index and commit snapshots
Git commits represent snapshots rather than simply storing a list of line edits. Git can use object reuse and packfiles to store content efficiently. The index represents the snapshot staged for the next commit and may include multiple stages while resolving conflicts.
11.4 Refs and reflog
References include branch names and tags. HEAD often points symbolically to a branch. The reflog records recent movements of references in a local repository and can help recover commits after reset or branch movement.
_The reflog in action, including recovering a commit after reset --hard, is under 16.6._
Reflogs are local and expire according to configuration/maintenance. They are not a substitute for backups or remote copies.
git reflog
git show HEAD@{1}11.5 Packfiles and garbage collection
Git can compress and combine objects into packfiles to reduce storage and improve performance. Maintenance and garbage collection prune unreachable objects according to repository rules. Avoid manually deleting internal .git data.
11.6 Plumbing and porcelain
Porcelain commands are designed for everyday workflows (status, add, commit, switch). Plumbing commands expose lower-level repository operations. Plumbing can be valuable for tooling, but scripts should account for stable output formats and version compatibility.
Quiz
? What does a tree object contain?
- File contents :: That is a blob.
+ Names, modes and the IDs of blobs and subtrees :: As shown by `git cat-file -p HEAD^{tree}`.
- The commit message :: That lives in the commit object.
- The reflog :: The reflog is separate, local metadata.
? Two files have identical content. How many blobs does Git store for them?
+ One :: `.env.example` and `notes.md` (both empty) shared blob `e69de29…` in the real `ls-tree` output.
- Two :: Content addressing deduplicates.
- None :: Empty files are still stored.
- It depends on the file names :: Names are stored in trees, not blobs.
? Which statements about the reflog are true? (select all that apply)
+ It records where HEAD and branches pointed recently. :: The real run listed each reset.
+ It is local to your repository. :: It is not pushed.
+ Entries expire. :: Garbage collection prunes old entries.
- It is a replacement for backups. :: The course warns against relying on it.