Skip to content

fix(sequencer): clear orphaned state file after git rebase --abort#737

Merged
aviator-app[bot] merged 3 commits into
masterfrom
fix/orphan-sequencer-state-after-git-abort
May 11, 2026
Merged

fix(sequencer): clear orphaned state file after git rebase --abort#737
aviator-app[bot] merged 3 commits into
masterfrom
fix/orphan-sequencer-state-after-git-abort

Conversation

@simsinght

Copy link
Copy Markdown
Contributor

Summary

When av sync/av restack hits a rebase conflict, sequencer state is persisted to .git/av/stack-{sync-v2,restack}.state.json so the operation can resume. If the user runs git rebase --abort directly (instead of av {sync,restack} --abort), the rebase ends but the av state file is left behind. Subsequent av {sync,restack} invocations honor the orphaned state — re-using its cached CurrentSyncRef and BranchingPointCommitHash — and replay the same stale rebase, producing spurious conflicts.

Fix

  • Add Repo.IsRebaseInProgress() in internal/git/git.go — checks for .git/rebase-merge/ or .git/rebase-apply/ directories (both removed by git rebase --abort).
  • In cmd/av/restack.go and cmd/av/sync.go, after loading a state file in readState(), verify a rebase is actually in progress. If not, treat the state as orphaned, clear the file, and return nil so the caller plans fresh from av.db.
  • cmd/av/reparent.go is unchanged — it already always creates fresh state and doesn't read the file.

This corresponds to option (1) from the design sketch in #734 — the most conservative fix targeting the exact trigger.

Reproduction

e2e_tests/testdata/script/restack_external_rebase_abort.txtar reproduces the bug:

  1. Stack: main → stack-1 → stack-2.
  2. Add a conflicting commit on stack-1.
  3. av restack from stack-2 → conflicts, persists state file.
  4. git rebase --abort → REBASE_HEAD cleared, av state file orphaned.
  5. git checkout stack-1.
  6. av restack --current (no-op for stack-1 as it has no children to restack).
    • Without fix: orphan is honored; CurrentSyncRef=stack-2 is reused; same conflict reproduced. Test fails.
    • With fix: orphan detected and cleared; fresh --current plan runs and reports done. Test passes.

Verified locally: test fails on master, passes with the fix.

Test plan

  • go build ./...
  • go tool golangci-lint run (0 issues)
  • go test ./e2e_tests/ (all pass)
  • go test ./internal/git/... ./internal/sequencer/... ./cmd/av/... (all pass)
  • New regression test fails on master, passes on this branch

Closes #734

When `av sync` or `av restack` hits a rebase conflict, sequencer state is
persisted to `.git/av/stack-{sync-v2,restack}.state.json` so the operation
can resume. If the user runs `git rebase --abort` directly (instead of
`av {sync,restack} --abort`), the rebase ends but the av state file is
left behind. Subsequent `av {sync,restack}` invocations honor the orphaned
state — re-using its cached `CurrentSyncRef` and `BranchingPointCommitHash`
— and replay the same stale rebase, producing spurious conflicts.

Add `Repo.IsRebaseInProgress()` (checks `.git/rebase-merge/` and
`.git/rebase-apply/`) and use it in the `readState` paths of both
`av restack` and `av sync`. If a state file is loaded but no rebase is
actually in progress, treat the state as orphaned, clear it, and fall
through to fresh planning from `av.db`.

Includes an e2e regression test (`restack_external_rebase_abort.txtar`)
that fails on master and passes with this fix.

Closes #734
@simsinght simsinght requested a review from a team as a code owner April 29, 2026 23:19
@aviator-app

aviator-app Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Current Aviator status

Aviator will automatically update this comment as the status of the PR changes.
Comment /aviator refresh to force Aviator to re-examine your PR (or learn about other /aviator commands).

This PR was merged using Aviator (commit abe5de4).


See the real-time status of this PR on the Aviator webapp.
Use the Aviator Chrome Extension to see the status of your PR within GitHub.

@aviator-app

aviator-app Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

✅ FlexReview Status

Common Owner: aviator-co/engineering (expert-load-balance assignment)
Owner and Assignment:

  • aviator-co/engineering (expert-load-balance assignment)
    Owned Files
    • 🔒 cmd/av/reorder.go
    • 🔒 cmd/av/restack.go
    • 🔒 cmd/av/sync.go
    • 🔒 internal/git/git.go
    • 🔒 e2e_tests/testdata/script/restack_external_rebase_abort.txtar

Review SLO: 7 business hours if PR size is <= 200 LOC for the first response.

@aviator-app aviator-app Bot requested a review from brain-crystal April 29, 2026 23:19

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a mechanism to detect and clear orphaned state files when a Git rebase is aborted externally (e.g., via git rebase --abort). It adds an IsRebaseInProgress method to the Repo struct and updates the readState functions in restack.go and sync.go to verify the rebase status before proceeding. An end-to-end test is included to verify the fix. I have no feedback to provide.

Comment thread cmd/av/sync.go
} else if err != nil {
return nil, err
}
if !vm.repo.IsRebaseInProgress() {

@jainankit jainankit May 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should do some check in av reoder as well.

`av reorder` persists state to `.git/av/stack-reorder.state.json` when a
cherry-pick conflict interrupts the reorder. If the user runs
`git cherry-pick --abort` directly (instead of `av reorder --abort`), the
cherry-pick ends but the av state file is left behind, and subsequent
`av reorder` invocations either error with "reorder already in progress"
or attempt to operate on stale state.

Apply the same orphan-detection pattern as restack/sync: if the state file
loaded but no cherry-pick is in progress, treat the state as orphaned,
clear it, and either error cleanly (`--continue` / `--abort`) or fall
through to a fresh reorder.

Adds `Repo.IsCherryPickInProgress()` for symmetry with
`IsRebaseInProgress()`.

Per @jainankit's review on #737.
@brain-crystal brain-crystal removed their request for review May 11, 2026 18:14
@aviator-app aviator-app Bot merged commit abe5de4 into master May 11, 2026
4 of 5 checks passed
@aviator-app aviator-app Bot deleted the fix/orphan-sequencer-state-after-git-abort branch May 11, 2026 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

av restack/sync reuses stale sequencer state after git rebase --abort, causing spurious conflicts

2 participants