4.5.7 · D1Software Engineering

Foundations — Git internals — objects (blob, tree, commit, tag), DAG structure

1,996 words9 min readBack to topic

This page assumes you know nothing. We build every symbol the parent topic uses, one at a time, each one earning the next.


0. The very first idea: bytes

Picture a file as a row of little boxes, each holding one number.

Figure — Git internals — objects (blob, tree, commit, tag), DAG structure

1. A hash: a fingerprint you can compute

The specific machine Git uses is called SHA-1 — see Hashing & SHA-1 for the gears inside. For us, treat it as a black box that turns "content" into "a name."

Figure — Git internals — objects (blob, tree, commit, tag), DAG structure

Let us read every symbol in that line, because the parent note uses all of them:

  • type ::: a word telling what kind of object this is (blob, tree, commit, tag).
  • size ::: the count of content bytes, written as ordinary digits.
  • \0 ::: one "null byte" (the number 0) that marks where the header ends and content begins.
  • + (here) ::: means "stick these byte-lists next to each other," not arithmetic.

2. Hex digits — the alphabet of the name


3. Key–value store: names filed away

Figure — Git internals — objects (blob, tree, commit, tag), DAG structure

4. Arrows, graphs, and "no loops allowed"

Git links its named objects with arrows. To read the topic's central picture, you need three graph words.

Figure — Git internals — objects (blob, tree, commit, tag), DAG structure

5. The four objects, now that every symbol is earned

With bytes, hash, key–value, and DAG in hand, the four object types are just four flavours of "named content."

Two more words the parent leans on:

  • mode ::: a small number like 100644 recording file permissions (readable/executable), stored in the tree line.
  • snapshot ::: a complete picture of the whole project at one moment — a commit reaches every byte through its tree, so it is a snapshot, not a diff.

6. Branches and HEAD: movable sticky-notes


Prerequisite map

bytes = a list of numbers

hash = fingerprint of bytes

content vs name

hex 40-char oid

key-value store

four objects blob tree commit tag

graph dots and arrows

directed one-way arrows

acyclic no loops = DAG

Git internals topic

movable pointers branch and HEAD

Each arrow reads "is needed to understand." Notice hashing (B) feeds both the objects and the acyclicity — that is the double duty at Git's core.


Equipment checklist

Test yourself — cover the right side and answer aloud.

What is the "content" of a file, in Git's meaning?
Exactly its list of bytes — no name, no path, no permission.
What does a hash guarantee about identical inputs?
Same bytes always produce the same fixed-length code.
Can you run a hash backwards to recover the bytes?
No — it is one-way.
What three parts make up store before hashing?
type, then a space, size, a \0 byte, then the content.
Why include the header instead of hashing content alone?
It makes the name type-aware and length-framed, so different object kinds can't be confused.
What is the SHA-1 of an empty blob and why?
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 — it is SHA1("blob 0\0").
Why are the 40 characters written in hex?
To turn arbitrary (often unprintable) fingerprint bytes into safe, typeable symbols.
In a key–value store, what is Git's key?
The hash (oid) of the value's bytes.
Name the two free gifts of content-addressing.
Deduplication (same bytes stored once) and integrity (corruption changes the key).
What do "directed" and "acyclic" each mean?
Directed = one-way arrows; acyclic = following arrows never loops back.
Why is Git's history forced to be acyclic?
A commit's hash depends on already-existing objects, so arrows can only point to the past — no future loop is possible.
Where do filenames and modes live?
In the tree object's lines, not in the blob.
Is a branch a Git object?
No — it's a movable file holding one commit hash; HEAD points to the current branch.