Caution
This software is vibe coded.
An educational tool for explaining git internals live. Point it at a repo,
run git commands in a terminal, and watch the object database change in real
time: blobs, trees, commits, tags, references, HEAD, and the staging area —
parsed straight from .git, never by shelling out to git.
./demo.sh my-demo # create a fresh, presentation-safe demo repo
deno task start my-demo # serve the visualizer
# open http://localhost:8422 and run git commands inside my-demoThe teaching flow (also printed by demo.sh):
| step | command | what the audience sees |
|---|---|---|
| 1 | git add a.txt |
a blob appears + an index row — before any commit exists |
| 2 | git commit |
a tree and a commit appear; main materializes |
| 3 | more commits | commits chain via parent pointers; unchanged blobs are shared |
| 4 | git switch |
HEAD moves — zero new objects |
| 5 | branch + commits | the DAG visibly diverges |
| 6 | git tag -a v1 |
an annotated tag object |
| 7 | git merge |
a commit with two parents |
| 8 | git gc |
loose objects vanish into a packfile (detected and labeled) |
Click any node to see its parsed fields next to the raw zlib-inflated bytes
(hex + ascii, header highlighted) and its on-disk path — the "a commit is just a
small zlib-compressed text file" reveal. #<sha-prefix> in the URL deep-links
to a node.
- Loose objects only. Packfiles are detected and shown as a banner with
object counts, not parsed. Demo repos should be freshly
git init-ed, never cloned;demo.shdisables auto-gc. - Index v2 is parsed (the staging pane); v3/v4 degrade to a notice
(
demo.shpinsindex.version 2). - Working-directory status is out of scope (it isn't stored in
.git). - SHA-1 repos (the default object format).
A single Deno process watches .git (Deno.watchFs), ignores *.lock/temp
churn, waits ~200 ms of quiescence, then re-scans the whole directory and pushes
one atomic snapshot over a WebSocket — so the UI never renders a torn
mid-commit state. The frontend is dependency-free vanilla JS + SVG.
src/git/objects.ts loose objects: zlib inflate + commit/tree/blob/tag parsing
src/git/refs.ts refs/**, packed-refs, HEAD (symbolic/detached/unborn)
src/git/index.ts .git/index (DIRC v2)
src/git/pack.ts packfile detection + object counts from .idx
src/snapshot.ts full-rescan orchestrator
src/watcher.ts debounced fs watcher
src/server.ts static UI + WebSocket broadcast
static/ the UI (no build step)
deno task testFixture repos are built with real git as ground truth (hermetically — your global git config is ignored); the code under test never invokes git.