[[ -d "$REPO/.git" ]] || { echo "FATAL: not a git repo" >&2; exit 1; }
Root cause / fix strategy. The fleet rewrite campaign force-reset the repo to the rewritten remote (July-22 state), orphaning 154 unpushed commits. Because the repo never pushes, the rewritten remote no longer contains them — and after the campaign's reflog-expiry/GC, the only copy of that history is the ops bundle taken 3 minutes before the reset. The fix restores from that bundle, but only after proving the bundle is trustworthy: bundle head must equal the ops-ref (last commit before reset). No reset is performed until that check passes.
Step 0 — ops capture (3 min before reset), fleet-backup.sh:
git -C "$REPO" rev-parse refs/heads/main > /tmp/fleet-backups/$NAME.pre-reset-head # ops-ref
git -C "$REPO" bundle create /tmp/fleet-backups/$NAME.bundle --all # full object snapshot
git bundle verify /tmp/fleet-backups/$NAME.bundle # integrity gate
Step 1 — recovery, fleet-recovery.sh (core runbook logic):
set -euo pipefail
REPO="$1"; BRANCH="${2:-main}"
BUNDLE="/tmp/fleet-backups/$(basename "$REPO").bundle"
OPS_REF_FILE="/tmp/fleet-backups/$(basename "$REPO").pre-reset-head"
BACKUP_REF="refs/remotes/backup/$BRANCH"
# 1. preconditions
[[ -d "$REPO/.git" ]] || { echo "FATAL: not a git repo" >&2; exit 1; }
[[ -f "$BUNDLE" ]] || { echo "FATAL: bundle missing" >&2; exit 1; }
[[ -f "$OPS_REF_FILE" ]] || { echo "FATAL: ops-ref missing" >&2; exit 1; }
git bundle verify "$BUNDLE" >/dev/null || { echo "FATAL: bundle corrupt" >&2; exit 1; }
# 2. resolve bundle head for the branch
BUNDLE_HEAD="$(git bundle list-heads "$BUNDLE" \
| awk -v b="refs/heads/$BRANCH" '$2 == b {print $1; exit}')"
OPS_REF="$(cat "$OPS_REF_FILE")"
# 3. THE gate: bundle head == ops-ref (last commit before reset), else ABORT
[[ "$BUNDLE_HEAD" == "$OPS_REF" ]] || { echo "FATAL: bundle head $BUNDLE_HEAD != ops-ref $OPS_REF — refusing to reset" >&2; exit 1; }
# 4. never clobber uncommitted work
[[ -z "$(git -C "$REPO" status --porcelain)" ]] || { echo "FATAL: uncommitted changes — stash first" >&2; exit 1; }
# 5. fetch bundle into a namespaced ref (rewritten remote refs untouched)
git -C "$REPO" fetch "$BUNDLE" "refs/heads/$BRANCH:$BACKUP_REF"
# 6. cross-check the object actually fetched
[[ "$(git -C "$REPO" rev-parse "$BACKUP_REF")" == "$OPS_REF" ]] \
|| { echo "FATAL: fetch mismatch" >&2; exit 1; }
# 7. restore branch + worktree
git -C "$REPO" reset --hard "$BACKUP_REF"
# 8. postconditions
[[ "$(git -C "$REPO" rev-parse HEAD)" == "$OPS_REF" ]] || { echo "FATAL: post-reset HEAD mismatch" >&2; exit 1; }
git -C "$REPO" fsck --no-dangling
Why this works. A bundle is a self-contained object pack + ref list, so fetch <bundle> refs/heads/main:refs/remotes/backup/main imports all 154 commits and their trees/blobs without touching refs/remotes/origin/* or the rewritten branch; reset --hard backup/main then restores branch pointer and worktree (board JSONL, gitreins, code). The repo stays non-pushing — no push is ever attempted; refs/remotes/backup/* exists only locally. Post-recovery you can diff against the rewritten remote to quantify the campaign's damage: git log --oneline origin/main..backup/main (154 commits) and git diff --stat origin/main backup/main.
Built a full simulation in `/tmp/fleet-sim/fleet-repo`: 154 commits with growing `data/board.jsonl`, `gitreins`, `src/code.py`; captured backups via `fleet-backup.sh` (bundle + ops-ref `d4daff6…`); then simulated the campaign — reset to a 30-commit "July-22" state, deleted the branch, `reflog expire --expire=now`, `gc --prune=now` so the bundle was the *only* copy of the 154 commits. **Happy path (test 1) — all PASS:** - HEAD after recovery == ops-ref `d4daff603ab6d07d927e02c04b34ea282128be46` ✓ - `git log | wc -l` == 154 ✓; `status --porcelain` empty ✓ - `board.jsonl` = 154 lines, `diff` vs pre-reset copy **IDENTICAL** ✓ - `gitreins` and `src/code.py` **IDENTICAL** ✓ - `git fsck --no-dangling` clean ✓; `refs/remotes/backup/main` == ops-ref ✓; no `refs/remotes/origin/*` created ✓ **Edge cases (tests 2–8) — all abort cleanly with exit 1 and no mutation:** | Test | Input | Result | |---|---|---| | 2 | ops-ref tampered (bundle head ≠ ops-ref) | `FATAL: bundle head … != ops-ref … — refusing to reset`, HEAD unchanged ✓ | | 3 | bundle file missing | `FATAL: backup bundle missing` ✓ | | 4 | dirty worktree (correct ops-ref) | `FATAL: uncommitted changes`, dirty byte preserved ✓ | | 5 | branch `feature-x` absent from bundle | `FATAL: branch not present in bundle` ✓ | | 6 | path not a git repo | `FATAL: not a git repository` ✓ | | 7 | malformed ops-ref (`not-a-sha`) | `FATAL: ops-ref malformed` ✓ | | 8 | re-run after recovery (idempotency) | `RECOVERED … exit 0`, state stable ✓ | Cross-check: the repo reflog (`reset: moving to refs/remotes/backup/main` → `d4daff6`) independently confirms the ops-ref is the pre-reset HEAD. Note the first pass of edge test 1 hit a harness naming artifact (clone dir looked for `e1.bundle`) — re-run with the real bundle proved the mismatch gate fires *before* any reset.
{"model": "deepseek-v4-flash", "problem_class": "git-repo-fleet-rewrite-reset-recovery", "result": "passed", "tests": 15}