Skip to content
AFM Studio
  • Pages

    AFM Studio
  • Work
  • Lab
  • About
  • CV
  • Contact
  • Projects

    AksaraA searchable library for Otorita IKN's knowledge, where the server checks every reader's access across three levels
  • Daily TaqwaTamper-resistant prayer attendance system for ~2,000 OIKN government employees at Masjid Negara IKN
  • Lantara v2A permit engine for Otorita IKN where administrators add new permit types from a screen, without a developer
  • eKiosk IKNTwo control rooms for Nusantara: kiosk content management and live bus tracking with arrival times that grade themselves
  • E-Monev IKNA monitoring platform for Nusantara's 23-year build, tracking every unit's quarterly progress against 24 national KPIs
  • JDIH OIKNOIKN's public legal document portal, with a controlled publishing workflow and AI summaries that never leave the server
  • Jejak PenanamanA check-in app for IKN tree-planting events that proves each participant was on site with a geofenced selfie
  • Dashboard SAKTIA nightly pipeline and dashboard that replaces OIKN's manual budget downloads for all six of its budget units
  • DoseRxA bedside dose calculator for 127 drugs that rounds each dose to tablets and syrups Indonesian pharmacies sell
  • CubiqA speedcubing trainer with competition-grade timing and a solver I wrote for each of the 8 major puzzles
  • ScimotionAn interactive science library of 86 articles, each explained next to animations the reader can control
  • WA Daily Scrum BotA WhatsApp bot that chases missing standup reports for a 14-person team and flags tasks stuck for days

↑ ↓ to move · Enter to open · Esc to close

Git Rebase Simulator

A safe sandbox for practising rebase, hard reset and force-push, where commit ids change as in Git

Screenshots
Git commands you can practise safely
17
scenarios checked against real Git
9
shareable scenarios from everyday Git trouble
6
On this page

The problem

Rebase is the Git command developers fear most, and the fear is earned. It is usually explained as "moving commits onto a new base". It doesn't move anything. It writes new commits with new ids and leaves the originals in the repository, with nothing pointing at them. Almost every "I lost my work" panic, and its cure, the reflog, comes from that one misunderstanding.

Good visual tools exist, and Learn Git Branching is the best known. I link to it from the site. But the tools I looked at share three gaps. They use fake ids like C1 and C2, so a rebased commit still looks like the same commit. They hide commits that were left behind, so nobody learns how to recover them. And they have no file content, so there are no conflicts, which is exactly where rebase hurts. The simulator is for developers who use Git daily but don't trust rebase, and for people who teach it.

What I built

The simulator works the way Git stores data

I implemented Git's own storage model and let the drawing read from it. Every commit id is calculated from the commit's content, including its parent. So when a rebase gives a commit a new parent, its id changes on screen by itself. Commits are only ever added, never edited or deleted, unless you run cleanup. After every command in every test, a check confirms that nothing that existed before has changed or gone.

Left-behind commits stay on the board

After a rebase or a hard reset, the old commits stay visible, greyed out and with no branch pointing at them. A reflog panel lists every time a branch or HEAD moved, and what moved it. One click creates a branch at a lost commit, which is the same fix you would use in real Git.

Real files make real conflicts

Each commit carries actual file content. When a rebase can't apply cleanly, you get a three-way conflict with Git's own markers, and you continue, skip or abort as in Git. A comparison view runs merge and rebase from the same start, side by side. The histories look different, but the final files are identical, and a test checks that.

I checked it against real Git

A teaching tool that is plausibly wrong would train people to misunderstand rebase with confidence. So I wrote a script that runs the real Git program through nine scenarios, two against a bare repository acting as a remote, and records the results. The tests compare the shape of the history: parents, branch positions and which objects are new. They don't compare commit ids, because real Git mixes in the time and author. The site says so.

Unsupported commands say so by name

The simulator refuses pull on purpose, because pull hides the half of its job that rewrites history. Its error message tells you to use fetch followed by merge or rebase. A few advanced options are refused the same way. A confident wrong answer is the worst thing a teaching tool can give.

Result

The Git Rebase Simulator is live and open source under the MIT licence, in English and Indonesian, and works offline after the first load. It supports 17 Git commands, including interactive rebase and a simulated remote for push, fetch and force-push. Six ready-made scenarios, such as an accidental hard reset or a dangerous force-push, can be shared by link. I built it in about five hours on 5 August 2026, from a written spec.

Under the hoodTechnical detail for engineers
  • The engine is pure: (state, command) → { state, events }, with no React, DOM, Date or Math.random. Timestamps come from a virtual clock in state.
  • The object store is append-only; gc is the only deletion. The invariant runs after every command in every test: every prior object must still exist, byte-identical.
  • Hashes are the SHA-1 of each object's canonical serialisation, mirroring Git's loose-object format. Blob and tree ids match real Git exactly (checked against git ls-tree); commit ids differ because of timestamps and author identity.
  • SHA-1 is hand-written in lib/hash/sha1.ts (99 lines), checked against the RFC 3174 vectors. SubtleCrypto is async and browser-only, which would have made the engine impure and untestable in Node.
  • A session is a list of command lines. Replaying them rebuilds the store byte-for-byte, so a shared URL encodes the script.
  • pnpm fixtures:record (scripts/record-fixtures.mjs) shells out to the real git binary. It is development-only and never runs in CI or the browser build.
  • Refused by name: pull, --rebase-merges, criss-cross merge bases, reverting a merge without -m, dropping already-upstream commits by patch-id, and multiple remotes.
  • Hand-written parts: the gitrevisions parser (HEAD~3, HEAD^2, ref@{n}, short hashes), three-way merge over line arrays in lib/git/merge3.ts, and deterministic git log --graph lane layout in lib/layout/lanes.ts, snapshot-tested.
  • Reachability is recomputed from scratch on every change, never refcounted, so the orphan view can't drift.
  • Interactive rebase supports pick, reword, squash, fixup, drop and reorder, replayable as rebase -i --todo=pick:<oid>,squash:<oid>,….
  • The graft animation is driven by the engine's commits-replaced event (old-to-new id pairs), never inferred from the graph shape.
  • Commands: add, commit, branch, checkout/switch, merge, rebase, cherry-pick, reset, revert, tag, diff, log, status, reflog, gc, push, fetch.
  • Originally named Cangkok (Indonesian for grafting). The committer domain cangkok.local stays, because it is folded into every commit hash and changing it would invalidate the recorded fixtures.
  • The PRD said Indonesian first; the shipped app defaults to English at /en/, with Indonesian at /id/ and a locale-parity test.
  • Runtime dependencies: next, react, react-dom. No Git, hashing, graph-layout, animation or state library. 4 routes × 2 locales, about 2.0 MB static export. 186 tests in 21 files, about 11,700 lines, 32 commits.

Screenshots

Beranda
Sandbox
Scenarios
Compare

Hiring, or building something similar?

I'm open to full-time roles and select freelance work.