Your first AI pull request will often need rollback.
Plan that rollback before you merge anything.
You lack repo history on day one.
Agents still produce large and confident diffs today.
A rollback plan keeps that blast radius tiny.
What first rollback actually means
First rollback means undoing your own agent PR.
It does not mean rewriting team history casually.
You revert a branch you still control.
You leave other people's commits completely untouched.
Why juniors stall on revert
You treat revert as an admission of failure.
It is a safety move, not a performance review.
You also wait for perfect understanding of every hunk.
That wait lets CI keep building a bad branch.
Step 1: Freeze merge before you diagnose
Do not keep generating patches during a bad merge.
Stop the agent, the pipeline, and extra pushes now.
- Mark the PR as draft if GitHub still allows it.
- Cancel running CI on that branch right now.
- Tell your reviewer the branch is under rollback.
gh pr ready --undo
gh run cancel --branch "$BRANCH"
git status -sb
Those three commands buy you quiet thinking time.
You need that quiet before you touch git history.
Step 2: Inventory every file the agent touched
You cannot revert a change you cannot list.
Ask git, not the chat log, for the truth.
BASE="${BASE_SHA:-origin/main}"
HEAD="${HEAD_SHA:-HEAD}"
git fetch origin
git diff --name-status "$BASE"..."$HEAD"
git diff --stat "$BASE"..."$HEAD"
git log --oneline "$BASE".."$HEAD"
Save that inventory into a local file immediately.
mkdir -p .onboarding
git diff --name-status "$BASE"..."$HEAD" \
> .onboarding/first-pr-files.txt
git diff "$BASE"..."$HEAD" \
> .onboarding/first-pr.patch
Read the name-status list before any revert.
Look for migrations, lockfiles, and generated assets.
Read the patch in three passes
You do not read the patch from top to bottom.
You read it in three passes with git only.
- Read names first, then stats, then one scary file.
- Skip vendor folders until the end of the review.
- Stop when you cannot explain a hunk out loud.
git diff --name-only "$BASE"...HEAD | wc -l
git diff --stat "$BASE"...HEAD | tail -n 1
If the file count exceeds the ticket's expected paths, revert.
A junior should not debug a thirty-file agent surprise.
Step 3: Choose revert or fix-forward
Use a hard table. Do not improvise under pressure.
| Signal | Prefer revert | Prefer fix-forward |
|---|---|---|
| Files outside the ticket | Yes | No |
| Tests red on your branch | Yes | Only if one test fails |
| Schema or migration changed | Yes | No |
| Reviewer already approved | Ask first | Maybe |
| You cannot explain one hunk | Yes | No |
If two or more Yes cells fire, revert.
Fix-forward is for a single, obvious typo only.
Write the decision into the same onboarding folder.
cat > .onboarding/rollback-decision.md <<'EOF'
# First PR rollback decision
- Ticket:
- Files outside ticket:
- Tests:
- Migrations:
- Choice: revert | fix-forward
- Why:
EOF
Fill every bullet before you run git revert.
Empty bullets mean you are still guessing, so stop.
Step 4: Revert on a fresh branch
Never reset shared main on day one.
Never force-push a branch others already pulled.
- Create a rollback branch from current HEAD.
- Revert the merge commit or the PR range.
- Keep the original branch for later autopsy.
set -euo pipefail
TICKET="${TICKET:-ONBOARD-0}"
SAFE="rollback/${TICKET}-first-pr"
git switch -c "$SAFE"
# If the PR was a single merge commit:
git revert -m 1 "${MERGE_SHA}" --no-edit
# If the PR was a linear range:
# git revert --no-edit "${BASE}".."${HEAD}"
If revert conflicts, abort and re-read the inventory.
git diff --name-only --diff-filter=U
# After you understand each conflict:
# git revert --abort
Do not ask an agent to resolve conflicts yet.
Conflict markers hide product rules you just learned.
Step 5: Prove the tree matches the base
A revert is not done when git says success.
A revert is done when tests match the base branch.
git fetch origin
git diff --stat origin/main...HEAD
Pin the test command from the README only.
Do not invent npm scripts the agent suggested.
# Proposed example. Replace with the README command.
# npm test
# go test ./...
# pytest -q
If tests fail on the rollback branch, stop shipping.
Your revert missed a generated file or a migration.
Step 6: Open a tiny rollback PR
The rollback PR should contain almost no story.
It should contain the inventory and the decision file.
- Title it with the original ticket id.
- Link the failed PR in the first line.
- Paste the name-status list in the body.
git add .onboarding/first-pr-files.txt \
.onboarding/rollback-decision.md
git commit -m "revert: ${TICKET} first AI PR"
gh pr create --draft --title "revert: ${TICKET}" \
--body-file .onboarding/rollback-decision.md
Keep the original PR closed or converted to draft.
Do not delete it; you need the transcript later.
Where a free coding agent still helps
You still need a second pair of eyes on the diff.
You do not need that pair of eyes to rewrite files.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode is an open-source coding assistant for local work.
It offers free model access and a free server option.
Use it to narrate the patch, not to apply another patch.
Paste the inventory file and ask for a file-risk list.
Ask which paths look like migrations or generated code.
Then you run git while the agent stays in explain mode.
That split matters on a junior's first hour.
Explanation is cheap, but a second bad patch is not.
A reproducible autopsy script
Save this script under scripts in your clone.
Run it from the repo root on your PR branch.
#!/usr/bin/env bash
# Proposed local helper. Not team policy.
set -euo pipefail
BASE="${1:-origin/main}"
OUT="${2:-.onboarding}"
mkdir -p "$OUT"
git rev-parse --abbrev-ref HEAD > "$OUT/branch.txt"
git diff --name-status "$BASE"...HEAD > "$OUT/name-status.txt"
git diff --stat "$BASE"...HEAD > "$OUT/stat.txt"
git log --oneline "$BASE"..HEAD > "$OUT/commits.txt"
echo "Risky paths:" > "$OUT/risks.txt"
if command -v rg >/dev/null 2>&1; then
rg -n -i "migration|schema|lock|generated|dist/" \
"$OUT/name-status.txt" >> "$OUT/risks.txt" || true
else
grep -Ei "migration|schema|lock|generated|dist/" \
"$OUT/name-status.txt" >> "$OUT/risks.txt" || true
fi
echo "Inventory written to $OUT"
Label this as a proposed local helper, not team policy.
Your new team may already have a revert runbook.
Commit the script only if the team wants it.
Do not sneak tooling into the rollback PR itself.
Limitations
This workflow assumes you still own the branch.
It assumes main is protected and you can open drafts.
It does not cover broken production traffic today.
It does not cover signed commits you cannot reproduce.
Revert can miss submodule pointers and LFS files.
It can also miss squashed commits on a rewritten branch.
The decision table is a heuristic, not a proof.
Two yes cells do not replace a staff engineer's call.
Free model access will not know your production topology.
A free server will not hold your private incident facts.
Do not paste secrets, tokens, or customer data into prompts.
Who should not use this approach
Skip this if you are not the PR author.
Skip this if the change already shipped to customers.
Skip this if the repo uses a required merge queue.
Talk to the maintainer before any revert there.
Skip this if you cannot run the README test command.
A green revert you cannot test is still a guess.
Juniors on regulated codebases should wait for a buddy.
Pair on the revert and do not solo a schema undo.
Close the loop on hour one
Write three notes before you log off.
- What the agent changed outside the ticket.
- Which table signal made you choose revert.
- Which test command proved the tree was clean.
Those notes become your second-day review checklist.
They also keep the next agent session much smaller.
Practice this workflow on a throwaway clone first.
A free explain-only session can walk the inventory.
Keep every git command in your own terminal.
Top comments (0)