← Learn Runs in your browser

Step 1 A commit is a snapshot, not a diff

Many tools store a file's history as a list of changes. Git stores complete snapshots: each commit records what every tracked file looked like at that moment. Unchanged files are not copied — the commit just re-points at the identical existing content — so snapshots are cheap. The diffs you see in git log are computed by comparing two snapshots, not stored.

Two commits, side by side

Files that did not change between snapshots share the exact same stored object — Git never duplicates identical content.

Step 2 Working tree → staging → repository

A change moves through three areas. You edit files in the working tree, pick which edits to include with git add (the staging area / index), then freeze that selection with git commit into the repository. Staging is what lets you commit half your changes and keep the rest.

Click the commands to walk a change through

Working tree
app.js · modified
Staging area
Repository

The file is edited but not yet staged.

Step 3 The object model — everything is content-addressed

Git stores four kinds of object, each named by the hash of its own content. A blob is a file's bytes; a tree is a directory listing (names → blobs/trees); a commit points at one top tree plus its parent commit(s) and metadata. Same content always produces the same hash — that is how Git deduplicates and verifies integrity.

Type some content — watch its object id

git hash-object →

Change one character and the id changes completely; type the same text again and you get the same id. (Real Git prefixes a header and uses SHA-1/SHA-256; this is a stand-in hash for illustration.)

Step 4 History is a graph of commits

Each commit points back to its parent (a merge has two). Follow the arrows and you have the whole history — a directed acyclic graph. Git never edits a commit in place; "changing history" with rebase actually creates new commits and moves the branch pointer to them.

A small history

A
B
C
D
Arrows point to parents — newer commits know their ancestors, never the reverse. D is the tip; its parent is C, and so on back to the root A (which has no parent).

Step 5 A branch is just a pointer

A branch like main is a tiny file containing one commit id — nothing more. HEAD says which branch you are on. Commit, and the current branch pointer simply slides forward to the new commit. Creating a branch is instant because it only writes 40 characters.

Commit and branch — watch the pointers move

HEAD → main → C. A commit moves the current branch forward; a new branch is just another pointer at the same commit.

Step 6 Glossary

TermIn one sentence
blobThe stored bytes of one file, named by their hash.
treeA directory listing: names pointing at blobs and sub-trees.
commitA snapshot: one top tree + parent(s) + author/message.
staging area / indexThe set of changes that the next commit will include.
branchA movable pointer to a commit (just a file with an id).
HEADWhich branch (or commit) you currently have checked out.
DAGThe commit graph — each commit links back to its parent(s).
merge vs rebaseMerge joins two histories with a new commit; rebase rewrites commits onto a new base.

The whole idea: commits are content-addressed snapshots in a graph, and branches are just pointers into it. Almost every Git command is moving a pointer or adding an object — which is why it is so fast and so hard to actually lose work.

Send feedback

How this works

Stores only this report's id in your browser (localStorage) so a small note can pop up here once it ships. No account, nothing sent to us, no tracking. Clearing this site's data forgets it.

Changelog

What changed, and when. Newest first.

Loading…