Git DAG Simulator

Build a commit graph with four git commands and watch what each one does to it. Every commit, every ref move and every parent edge is drawn as it happens.

A worked example, rendered when the site was built. No JavaScript required. It is the scenario called A true merge: Both branches moved, on different files, so the merge makes a commit with two parents. With JavaScript on, this is replaced by the same engine with a command builder attached, so you can run these commands yourself and start from any of the five scenarios.

8 steps
Every command in the worked example, and what it did
StepCommandResultWhat happened
1git commit -m "Add the readme" (README.md)okCommit 194fc6e records a change to README.md on main, and it is a root commit, so it has no parent.
2git commit -m "Expand the readme" (README.md)okCommit 90031ec records a change to README.md on main, and its parent is 194fc6e.
3git branch featureokfeature now points at 90031ec. HEAD did not move, so you are still where you were.
4git checkout featureokHEAD is attached to feature, which points at 90031ec.
5git commit -m "Write the feature" (src/main.rs)okCommit 4f960b4 records a change to src/main.rs on feature, and its parent is 90031ec.
6git checkout mainokHEAD is attached to main, which points at 90031ec.
7git commit -m "Jot down the plan" (notes.txt)okCommit 14098f1 records a change to notes.txt on main, and its parent is 90031ec.
8git merge featuremergeA merge commit 9d3ba49 joins both histories. Its first parent is 14098f1, where HEAD was, and its second is 4f960b4, the tip of feature.
9d3ba49HEADmainMerge branch 'feature'14098f1Jot down the plan4f960b4featureWrite the feature90031ecExpand the readme194fc6eAdd the readme
3 refs
Where every ref points
RefPoints atCommit
HEADmain9d3ba49
feature4f960b44f960b4
main9d3ba499d3ba49
5 commits
The graph as a list, newest first
CommitRefs hereMessageParentsFile
9d3ba49HEAD, mainMerge branch 'feature'14098f1, 4f960b4none, a merge changes nothing itself
14098f1noneJot down the plan90031ecnotes.txt
4f960b4featureWrite the feature90031ecsrc/main.rs
90031ecnoneExpand the readme194fc6eREADME.md
194fc6enoneAdd the readmenone, this is the root commitREADME.md

The ids here are synthetic, drawn from a seeded generator rather than hashed. If you want the real function, the Hash Generator runs SHA-1 and its successors over your own input, and Hashprint turns a digest into a picture you can compare at a glance.

About this lab3 paragraphs

Four commands, and nothing else: commit, branch, checkout (including a detached HEAD) and merge, in both of its shapes. A fast-forward moves a ref along a chain that already exists and makes no commit; a true merge makes one commit with two parents, and the drawing shows both edges. Commands are built from pickers rather than typed at a fake shell prompt, so every argument is a real choice from the repository in front of you.

Nothing here is random and nothing reads a clock. Commit ids are synthetic: seven hex characters from the site's seeded generator, not a real SHA-1, because teaching the graph does not need the hash function and a seeded id makes the whole repository reproducible. Pick a scenario, replay its commands, and you get the same ids every time, on any machine.

What it does not do is the rest of git. rebase -i, cherry-pick, reset, revert, stash, reflog and anything to do with remotes are recorded as deferred, and a merge that collides is marked rather than resolved: the lab shows you that a conflict happened and on which file, and it stops there. There is no diff editor.