Version Control Internals

Understanding Git's Use of SHA-1 and SHA-256

How content-addressable storage, object headers, and Merkle DAG trees create an immutable, tamper-evident history.

Git is an immutable content-addressable filesystem where every file, directory tree, and commit is stored by the cryptographic hash of its contents rather than its human-readable path. While Git originally standardized on 160-bit SHA-1 hashes to detect repository corruption and build a tamper-evident commit DAG, modern releases have introduced native support for 256-bit SHA-256 object formatting to safeguard against collision attacks.

In short

In Git, everything is an object addressed by hash(header + content). A 14-byte file "Hello, World!\n" prepended with "blob 14\0" produces the exact SHA-1 object ID 8ab686eafeb1f44702738c8b0f24f2567c36da6d. Because commit objects embed the hashes of parent commits and root directory trees, modifying even one character in an old commit breaks every subsequent commit hash in the history.

01. The Plain-Language Analogy

The Three-Ring Binder vs. The Interlocking Stone Arch

In an ordinary operating system directory, editing a text document is like unclipping a three-ring binder, swapping page 14 with a new sheet, and snapping the ring shut. The binder's spine and cover remain unchanged, leaving zero record that a substitution ever occurred.

In Git, every file is cast into a solid granite brick, with its weight, volume, and composition stamped onto its face as a cryptographic hash. The directory (tree) is a ledger listing the brick hashes. The commit is a keystone mortared directly on top of the stones below. If you try to swap a single granite brick from three years ago, the mortar joint no longer fits, the keystone fractures, and the entire archway collapses unless every subsequent stone in the wall is re-carved from scratch.

02. Step-by-Step Mechanics of Git's Object Database

Git manages exactly four fundamental object types inside the .git/objects/ directory, all formatted with a standardized header before hashing:

1. The Blob Object (blob)

Stores pure raw file content. Blobs store zero metadata—no filenames, no directory paths, and no execution permissions. Format: blob <content_size_in_bytes>\0<file_content>.

2. The Tree Object (tree)

Represents a directory. A tree serializes a list of directory entries, where each entry consists of file permissions (e.g., 100644 for normal files, 100755 for executables), the entry name, a null byte, and the 20-byte binary hash of the target blob or child tree.

3. The Commit Object (commit)

Points to a root tree object and one or more parent commit hashes. It captures the author and committer names, email addresses, UNIX timestamps, timezones, and the commit message.

4. The Tag Object (tag)

Provides a permanent annotated reference to an explicit commit, embedding a tagger signature, timestamp, and optional GPG/PGP cryptographic signature.

Disk Storage Layout (Fan-out Directories)

When Git writes object 8ab686eafeb1f44702738c8b0f24f2567c36da6d to disk, it compresses the payload with zlib and places it in .git/objects/8a/b686eafeb1f44702738c8b0f24f2567c36da6d. The first 2 hex characters serve as the directory name to prevent traditional filesystems from hitting performance bottlenecks with tens of thousands of files in a single folder.

03. Worked Example: Reproducing a Real Git Object Hash

Let us calculate a Git blob hash from scratch using standard command-line utilities and verify it against Git's internal engine:

Input Text: "Hello, World!\n" (14 bytes including newline)
# 1. Native Git hash-object calculation:
$ echo "Hello, World!" | git hash-object --stdin
8ab686eafeb1f44702738c8b0f24f2567c36da6d
# 2. Manual construction using printf and sha1sum:
$ (printf "blob 14\0"; echo "Hello, World!") | sha1sum
8ab686eafeb1f44702738c8b0f24f2567c36da6d -
Real Live Commit Dissection (from this repository):
$ git cat-file -p 4f57f52b0f081f12b16b13769d43ce287e07e51d
tree ba10250f117ba455bbbb6dcc86887ef13300bee6
author c-dev-2 <c-dev-2@users.noreply.github.com> 1778173271 -0700
committer c-dev-2 <c-dev-2@users.noreply.github.com> 1778173271 -0700
Complete site overhaul: redesigned homepage, new guides section...

The commit hash 4f57f52... is the SHA-1 of the exact UTF-8 text above prepended with "commit 251\0".

04. Common Misconceptions Corrected

Misconception 1: "Git uses SHA-1 as a security cipher to stop malicious hackers"

Linus Torvalds selected SHA-1 primarily as an integrity checksum to detect hardware corruption and accidental transmission errors, not as an unbreachable digital signature. However, because Git's security model assumes collision resistance, the 2017 SHAttered collision spurred Git to add hardened collision-detecting SHA-1 (sha1dc) and engineer a long-term transition to SHA-256.

Misconception 2: "Renaming a file in Git changes its blob hash"

The blob hash depends strictly on the file bytes, completely ignoring its filename. If you rename main.rs to app.rs without modifying its code, Git does not write a single new blob; it only updates the tree object to point the new filename to the existing blob hash.

Misconception 3: "Git stores file diffs between commits"

Unlike older VCS tools (CVS, SVN) that stored deltas, Git stores complete snapshots. Each commit references a full tree representing the entire repository state. Git only computes deltas during background garbage collection (git gc) to pack redundant objects into space-efficient .pack archives.

05. Git Object Format Comparison: SHA-1 vs. SHA-256

Property Git Legacy (SHA-1) Git Modern (SHA-256) Significance
Hash Bit Length 160 bits (20 bytes) 256 bits (32 bytes) Hex string length increases from 40 to 64 chars
Collision Resistance Broken (2^63 SHAttered) Secure (2^128 operations) Eliminates possibility of crafted colliding commit objects
Mitigation in Place sha1dc (Collision Detection) Native Algorithm Security Detects shattered attack patterns on object import
Initialization Flag git init git init --object-format=sha256 Supported natively in Git 2.29+

06. Primary Sources & Official References

Related Guides