feat(rewrite): print post-rewrite recovery instructions - #17
Conversation
Capture the pre-rewrite HEAD sha before the rewrite command runs and surface it afterwards, along with the exact `git reset --hard` command to undo the rewrite. When the filter-branch backend was used, also show the refs/original/ recovery path since filter-branch (unlike filter-repo) preserves originals there. Closes #7
There was a problem hiding this comment.
🔎 Agent review (claude-sonnet-5) — LGTM
REVIEW: LGTM
RESOLVES: full
Implements exactly what the plan and issue specify: pre-rewrite HEAD sha is captured right before the mutating subprocess call, RewriteResult threads backend info through cli.py, and the filter-branch refs/original/ recovery line only appears for that backend. Dry-run output is unchanged, tests cover both backends and the dry-run no-op case, and the full suite (76 tests) plus ruff pass cleanly.
1 nit — 1 inline on the diff
…-git-rewrite-7-feat-post-rewrite-recovery # Conflicts: # tests/test_cli.py
There was a problem hiding this comment.
🔎 Agent re-review (claude-sonnet-5, delta) — LGTM
REVIEW: LGTM
RESOLVES: full
The ref-type assumption in the filter-branch undo line is now fixed by checking whether the ref is already fully qualified before prefixing with refs/heads/, and new tests cover both filter-repo and filter-branch paths plus the dry-run no-extra-output case. No new bugs or scope creep found; only a trivial ruff-format nit (missing blank line after docstring in RewriteResult).
1 nit — 1 inline on the diff
Co-authored-by: gfargo-horizon-agent[bot] <294710345+gfargo-horizon-agent[bot]@users.noreply.github.com>
What
After a successful (non-dry-run) history rewrite, print the pre-rewrite HEAD sha and the exact recovery command(s) needed to undo it, tailored to whichever backend actually ran.
Why
Closes #7
Plane: OSS-294
How
backends.rewrite()now capturesgit rev-parse HEADimmediately before the mutating command runs and returns aRewriteResult(backend_name, pre_rewrite_sha)instead ofNone.cli._force_push_reminder()now takes theRewriteResultand prints:Pre-rewrite HEAD : <sha>andTo undo (filter-repo): git reset --hard <sha>whenever a real rewrite ran (filter-repo deletesrefs/original/by default, so this is its only recovery path).To undo (filter-branch): git reset --hard refs/original/<ref>line when the filter-branch backend was used (it preserves originals there), resolving the current branch viagit symbolic-refwhen--refswasn't given.cmd_strip,cmd_replace, andcmd_runthread theRewriteResultthrough to_force_push_reminder.--dry-runoutput is unchanged — the new recovery block is only printed on a real rewrite.Testing
tests/test_backends.py, plus new recovery-output tests intests/test_cli.py)ruff check)🤖 Generated by the harbor agent loop. Reviewed by a human before merge.
Closes #7