๐ฌ Chapter 13: Git Internals โ Behind the Curtain โ
Git's Three Types of Objects โ
Git's core is actually very simple โ it's essentially a key-value database. All data is stored as three types of objects:
text
Git's three core objects:
blob (data object): Stores file content
tree (tree object): Stores directory structure (file name + blob mapping)
commit (commit object): Stores commit info (author, time, message + pointer to tree)
Their relationship:
commit โ tree โ blob
โ โ โ
โ โ โโโ Actual file content
โ โโโ Directory structure and file names
โโโ Commit metadata + pointer to previous commitbash
# View Git objects
git cat-file -t HEAD
commit
# View commit object content
git cat-file -p HEAD
tree a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7
parent b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1
author Alice <alice@example.com> 1624182600 +0800
committer Alice <alice@example.com> 1624182600 +0800
feat: add welcome message
# View tree object
git cat-file -p a8b9c0d1
100644 blob f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6 index.html
100644 blob e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5 style.css
# View blob object
git cat-file -p f7a8b9c0
<!DOCTYPE html>
<html>
<head>
<title>My First Website</title>
</head>
<body>
<h1>Hello, Git!</h1>
<p>Welcome to my website!</p>
</body>
</html>SHA-1 Hash โ Git's Identity System โ
Git uses SHA-1 hash values to identify each object. The same content always produces the same hash.
bash
# Git calculates blob hash values like this
# Format: blob <content length>\0<actual content>
echo -n "Hello, Git!" | git hash-object --stdin
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 (example, actual value varies by environment)
# Same calculation every time (deterministic)
echo -n "Hello, Git!" | git hash-object --stdin
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 (example, actual value varies by environment)
# Change one character, completely different hash (avalanche effect)
echo -n "Hello, git!" | git hash-object --stdin
b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1 (example, actual value varies by environment)Refs โ Human-Readable Pointers โ
SHA-1 hashes are too hard for humans to remember, so Git uses "refs" to give them names.
bash
# A branch is just a pointer to a commit
cat .git/refs/heads/main
f4e5d6c7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3
# HEAD points to the current branch
cat .git/HEAD
ref: refs/heads/main
# Remote branch refs
cat .git/refs/remotes/origin/main
a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6
# The complete reference chain:
# HEAD โ refs/heads/main โ commit hash โ tree โ blobsPackfiles โ Git's Compression Technique โ
Although Git saves snapshots, it doesn't fully copy all files every time. When there are many files, Git automatically packs and compresses them.
bash
# Manually trigger garbage collection and packing
git gc
Enumerating objects: 42, done.
Counting objects: 100% (42/42), done.
Delta compression using up to 8 threads
Compressing objects: 100% (30/30), done.
Writing objects: 100% (42/42), done.
Total 42 (delta 12), reused 42 (delta 12), pack-reused 0
# View repository size
git count-objects -vH
count: 0
size: 0 bytes
in-pack: 42
packs: 1
size-pack: 8.50 KiB
prune-packable: 0
garbage: 0
size-garbage: 0 bytes