gitva
v1.6.0
Published
The visual anatomy of git: a visual tutorial taught from the internals upward, drawing a repository's .git as a live object graph in your browser.
Maintainers
Readme
gitva
the visual anatomy of git
git add a.txt b.txt → two blobs appear, two index entries point at them
git reset b.txt → the index entry goes; the blob survives, now unreachableGitva draws a repository's live object graph in your browser, to make one sentence obvious:
git is just a key-value store plus a few pointers
Put a terminal beside the browser and type. Hash an object, update the index, write a tree, commit, reset, tag — the canvas updates on its own within a second and flashes what changed.

- HEAD attached to
develop - A blob you right-clicked wears a red outline
- One unreachable blob drawn as a ghost
- Links from the trees to blobs show file names
- Links from the trees to sub-trees show folder names
- Everything is movable and collapsible: your own learning tool
Two promises
It never writes to the repository it watches. Not the index, not a cache, not a config
value. src/git.ts will only spawn git subcommands from a read-only allowlist, and sets
GIT_OPTIONAL_LOCKS=0 so git will not take a lock to be helpful either. It will not run git
gc or write a commit-graph for you, and does not nag you to either.
Everything it knows, it learns from git's own plumbing. No git library, no reimplemented format. It runs the commands it is teaching, so you can read what it does and then type it yourself.
Run
The tool has zero runtime dependencies; requires Node ≥20.
npm install -g gitva
cd some-repo
gitvaFrom a clone instead:
npm install && npm run build
npm install -gTry it out without a repo:
./demo.shIt will run gitva on a demo repo inside the project folder, and run some git commands each second. You'll see the updated live view of the repository.
./demo.sh 3- slows it down to 3 seconds per step./demo.sh 0- turns off automatic steps: you'll need to press Enter to run each step
Gitva also records your sessions as independent steps and allows you (or any viewer) to walk through them at any time.
The recording lives on the server side, and is persisted on disk (outside of the repo),
so you can restart gitva without losing the recording.
One gitva keeps a recording at a time. Start a second one on the same repository and it draws
everything the first one does — it just says on the command line that this run will not be saved,
and leaves the recording to the one that has it.
A step is what git did. A view is how you look at it. The server records the steps and is the only thing that writes one; a browser only ever reads them. Everything you do to what is on screen — expanding, collapsing, the toggles, pins, marks, the camera, the language, the theme — happens in your browser and reaches nobody else, and there is nothing a browser can ask the server to do. The repository is shared, the view is yours.
Because a step carries everything any view could draw, the recording is also all a browser needs: once it has arrived, losing the connection costs you nothing but the next step.
Usage
To get the up-to-date help page for the tool usage, run gitva --help.
If the repository is not specified - it defaults to the current folder. You can also run gitva before initializing
the git repository (no .git folder) - gitva will start and wait until you initialize the repo.
--serve binds every interface instead of loopback, so viewers can watch one repository from
their own browsers. Default is 0.0.0.0:4200 when passed without arguments.
Specifying host/port separately also works: --serve=10.0.0.2 or --serve :9000.
--port option overrides any port specified by the --serve.
--id NAME records all steps to the recording with this ID, instead of the folder path (default).
You can also copy the ID of current recording by clicking on it, on the top left of the page.
--fresh starts the recording over.
--learning starts with every commit in the view expanded, so viewers don't need to open commits manually.
What you see

Four columns, left to right: pointers and tags | commits | trees and blobs | index.
- Pointers and tags - branches, remotes, tags - everything that points somewhere
- Commits - all commits, each one can be expanded or collapsed
- Trees and blobs - tree and blob objects, including submodule gitlinks
- Index - whatever is currently in the Index, connected to the respective blobs
Unreachable objects are drawn as ghosts. Recently changed (added/modified) things are highlighted momentarily. Click anything to read what it is or inspect its content.
Controls
| | | |---|---| | ctrl+wheel | zoom the canvas | | drag background | move around | | double-click background | fit to width, centered on the point you clicked | | click | select: inspect it, highlight the path through it, copy its SHA | | hover | highlight what it links to | | right-click | mark with a red outline for tracking | | double-click a commit | expand or collapse what it links to | | double-click a tree | expand or collapse that subtree | | double-click an index entry | draw the blob its SHA names, beside the entry | | drag anything | pin it where you put it; shift+click unpins | | shift+click | unpin an object from a specific location back to the default one | | drag a column edge | change the size of the column | | click on SHA in the inspector | copy the SHA — and select that object, if it is on screen | | click a SHA in a tree's contents | select the blob or tree that line names, and copy its SHA | | click on file path in the inspector | copy absolute file path | | drag the inspector edge | resize the inspector — settings dock it along the bottom instead of the side, for a narrow screen | | reset view | drops every pin (reset to default object positions) and puts the columns width back | | f ←/[ →/] space i | fit · step back · step forward · pause · index | | p | presentation: hide every toolbar so the canvas has the whole window — press again to bring them back |
The view toolbar has additional controls:
- Expand all - expands all commits and trees
- Collapse all - collapses all commits and index entries (excluding trees)
- Index - show/hide Index column
- Unreachable - show unreachable git objects
- Links from unreachable - show links from unreachable objects to reachable ones
- Names - show names of files/folders over the links
- ☾ / ☀ Theme - switches the theme between dark and light (click 5 times for an easter egg theme)
- help/settings - show help window, edit user view-scoped settings
- Languages section - on the very top right, allows selecting the language
The recording toolbar has the following controls:
- Reset view - resets all your moved objects into their original positions
- Recording controls - allows going back and forth between the steps of the recording: does not pause anything server-wise, scoped for your own view only
Big repositories
Gitva loads the last 1000 commits. If your repository has more commits - the oldest ones will not show up. If the repository has more than 12,000 objects, or more than 400 staged paths - some features might be disabled due to performance reasons, like tracking unreachable objects, or showing only part of the Index.
Building it
npm install
npm test
npm start -- /path/to/repoReferences and stack
References:
CLAUDE.md- instructions for agents maintaining this projectdocs/INITIAL_DESIGN.md- initial vision & the prompt that was used to create the first version
Stack:
- TypeScript
- Canvas 2D
- ESLint / Prettier
Use the canvas in your own page
The canvas ships as a library, so a page that is not gitva can draw the same object graph: a tutorial that shows what each command does, side by side with the text explaining it.
npm install gitvaOr from a CDN, with no build step at all - gitva and gitva/canvas are the same module:
<script type="module">
import { mount } from 'https://esm.sh/gitva';
</script>import { mount } from 'gitva/canvas';
const canvas = mount(document.getElementById('graph'), {
theme: 'light',
onSelect: (shape) => console.log(shape?.oid),
});
for (const step of steps) canvas.show(step); // draw a step
canvas.goto(0);You get the object graph and every gesture on it - drag to pin, drag empty space to pan, wheel to scroll, ctrl-wheel to zoom, double-click to expand a commit, a tree or an index entry, right-click to mark, shift-click to unpin, and a column edge to drag. Give the element a size: the canvas fills it.
The toolbars are yours to build. You can use these methods to control the canvas:
canvas.resetView(); // every pin out, every column back - the reset view button
canvas.unpin(id); // or just the one
canvas.setView({ showIndex: false }); // the index, unreachable and links toggles
canvas.expandAll(); // and canvas.collapseAll()
canvas.step(-1); // walk the recording; also goto(i), scrubTo(i), live()
canvas.settings.showNames = false; // then canvas.schedule()
canvas.fitCamera(); // the way back from anywherecanvas.recording holds the steps, the cursor and the view to read them off, and onChange
tells you when a gesture - or one of these calls - moved a pin, a mark, a column or the view,
so a page that keeps any of that has one place to write it down.
It never talks to a server, and there is nothing to configure: it draws the steps you hand
it. A step is what git did, so steps recorded months ago draw exactly as they did then.
samples/webapp/ is a working page of exactly that: nine commands, one slide each.
npm install && npm start in that folder. samples/webpage/index.html is the same idea
with nothing around it - one file, three steps inline, the canvas off a CDN. Open it in a
browser; there is nothing to install.
To get some, run gitva on a scratch repository, type the commands you want to teach, and take the recording off the event stream:
curl -sN -m 3 localhost:8080/events | grep -m1 '^data: \[' | cut -c7- > steps.json