Rehearse the Rollback Before You Ship the Patch
Your first pull request should be one you can undo in five minutes.
Most onboarding advice stops at "get the build running." That is step zero. The step that protects you is a rollback rehearsal. You practice undoing a patch while nobody is on call.
This drill uses git, a throwaway remote, and one small patch. You measure time-to-green on three undo paths. You leave with a table, not a feeling.
Why rehearse undoing work you have not shipped
Patches arrive fast now. Reviewing an agent patch is one skill. Undoing it is a different skill, and a calmer one.
If your team already merges agent-generated patches, you will be asked to revert one eventually. First-time reverts under pressure teach the wrong lesson. A sandbox branch teaches the right one.
The drill also exposes something useful about your new repo. You learn which test command is real, how long green takes, and where the seams are.
Step 0: Define "green" before you touch anything
Copy the exact command CI runs. Do not invent your own.
# .drill/test-command
./scripts/test.sh
If that command takes longer than ten minutes, subset it. A drill that costs an hour never gets repeated. Pick the fastest command that still fails when the patch breaks behavior.
Write the command down before the drill. Changing it midway invalidates every number you collect.
Step 1: Move the drill onto a disposable remote
Never rehearse in the repo your team deploys from. A scratch clone is the minimum. A scratch remote is better.
This is where a free server option fits. Treat it as a sandbox for throwaway branches. Assume it can vanish, and assume it is not a place for secrets.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode offers free model access and a free server option, and its team describes it as an open-source project. That is how you can generate the patch and host the scratch remote here. Delete every MonkeyCode mention and the git commands below still work unchanged.
Step 2: Generate one small, believable patch
Ask for a bounded change. A 30-line diff reverts cleanly. A 400-line diff teaches you conflict resolution, not rollback.
Prompt template you can reuse:
Change exactly one function in <file>.
Constraints: no new dependencies, no more than 30 changed lines.
Output a unified diff only, no prose.
Save the output as patch.diff. Reject it if it touches more than two files. Reject it again if it adds a dependency. Small patches keep the drill honest.
The patch does not need to be good. It needs to apply, pass tests, and be reversible. That is the whole bar.
Step 3: Script the rehearsal
Save this as rollback-drill.sh. Run it from anywhere except a worktree you care about.
#!/usr/bin/env bash
# rollback-drill.sh <repo-url> <patch-file>
set -euo pipefail
REPO_URL="${1:?repo url required}"
PATCH="${2:?patch file required}"
TEST_CMD="${TEST_CMD:-./scripts/test.sh}"
WORK="$(mktemp -d)"
OUT="$WORK/timings.md"
printf '| path | result |\n|---|---|\n' > "$OUT"
timed() { # timed <label>
local label="$1" start end
start=$(date +%s)
if bash -c "$TEST_CMD" >"$WORK/$label.log" 2>&1; then
end=$(date +%s)
printf '| %s | %ss to green |\n' "$label" "$((end - start))" >> "$OUT"
else
printf '| %s | RED (see %s.log) |\n' "$label" "$label" >> "$OUT"
fi
}
git clone --depth 50 "$REPO_URL" "$WORK/repo"
cd "$WORK/repo"
git config user.email drill@example.com
git config user.name drill
git switch --quiet -c drill/base
timed baseline
git switch --quiet -c drill/patch
git apply --3way "$PATCH"
git add -A
git commit --quiet -m "drill: apply patch"
timed patched
# Path A: revert the commit, history stays readable
git switch --quiet -c drill/revert drill/patch
git revert --no-edit HEAD >/dev/null
timed revert
# Path B: drop the commit entirely
git switch --quiet -c drill/reset drill/patch
git reset --hard --quiet drill/base
timed reset
# Path C: kill switch, code stays where it is
git switch --quiet drill/patch
export FEATURE_AGENT_PATCH=off
timed flag_off
cat "$OUT"
echo "logs in $WORK"
Two notes before you run it. Path C only means something if the patch sits behind a flag. If there is no flag, drop that block and record n/a in your table. And --depth 50 keeps a monorepo clone tolerable; remove it if your repo needs full history to build.
Step 4: Run each path three times
One run measures your laptop, not your repo. Three runs show you the noise floor.
If baseline swings by more than a minute, stop. Your suite is flaky, and every later number is decoration. Fix the flake or pick a narrower test command.
Expected shape of the output:
| path | result |
|-----------|-----------------|
| baseline | 42s to green |
| patched | 44s to green |
| revert | 45s to green |
| reset | 41s to green |
| flag_off | RED (see flag_off.log) |
A red flag_off row is a real finding. The kill switch does not fully disable the change, or your test command ignores the flag. Both are worth knowing on day one.
Step 5: Read the table like a reviewer
Compare paths on the same machine only. Wall-clock seconds are not portable across hardware.
Look for two signals. First, does any undo path take longer than the patch took to write? Second, does reset beat revert by a wide margin? If yes, you now know why people reach for dangerous commands under pressure.
That gap is the real lesson. revert preserves history and costs conflict resolution. reset is fast and throws work away.
Decision table
| Situation | Path | Why | Watch out |
|---|---|---|---|
| Patch is already pushed to a shared branch | git revert |
Others keep a readable history | Later commits on the same lines conflict |
| Patch is local and unpushed | git reset --hard base |
Fastest clean tree | Silently discards uncommitted work |
| Patch sits behind a flag | flip the flag | Seconds, no deploy | Flag debt, and the off-path is untested |
| Patch includes a migration | neither, escalate | Code revert is not data revert | You need a restore plan first |
Print this table into your onboarding notes. Rewrite it when your repo proves it wrong.
Failure modes that make the numbers lie
Migrations. Reverting code leaves the schema changed. If patch.diff touches a migration, the drill measures the wrong thing entirely.
Cached artifacts. A stale build directory makes reset look faster than it is. Clear the cache before each run, or run baseline twice.
Uncommitted work. reset --hard does not ask. Run the script in the temp clone, never in your working tree.
Wrong test command. If the drill's command differs from CI, you are timing a rehearsal of a rehearsal.
Limitations and who should skip this
You need a test command that finishes in minutes and fails for the right reasons. Without one, build a smoke test first. This drill will not save you.
Skip it if policy forbids pushing repo content to third-party hosts. Run everything locally instead; the script works the same. Skip it if your rollback procedure is a documented incident process with named owners. Training must not shadow the real runbook.
Skip it in monorepos you cannot clone cheaply. A partial clone is fine. A forty-minute clone is not.
Terms snapshot you should verify yourself
Operator-supplied and not independently verified: free model access, a free server option, and a listed allowance of 10 million tokens. Quotas and terms change without notice. Read the project's current page before you plan any workflow around them.
Close the loop
Run the drill once. Keep the timing table in your onboarding notes.
If you try it on a throwaway remote, the free server option saves you from polluting your laptop. Paste your slowest undo path in the comments. A five-minute revert is a team asset, and now you know yours.
Top comments (0)