Skip to content

fix: put staged changes back when a rebase completes - #288

Open
dfaure-kdab wants to merge 1 commit into
narnaud:mainfrom
dfaure-kdab:wip/dfaure/put-staged-changes-back
Open

dfaure-kdab wants to merge 1 commit into
narnaud:mainfrom
dfaure-kdab:wip/dfaure/put-staged-changes-back

Conversation

@dfaure-kdab

@dfaure-kdab dfaure-kdab commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

git rebase --autostash replays its stash into the working tree only, so a
staged modification came back unstaged on success, not just on abort. Only
the abort path compensated, and drop, update and reword saved nothing at
all, so every rebasing command quietly unstaged the user's work.

Restore the saved patch on the RebaseOutcome::Completed arm and in every
after_continue handler too, through one helper, and hand over what cannot be
replayed rather than dropping it. Why it applies three-way against a
rehearsed copy of the index rather than resetting is in Spec 014 and on the
helper itself; the cost is a diff of the index per rebase, and a copy of it
plus two applies per restore.

Two recovery paths change with it: run_rebase_or_abort now aborts a rebase
its own run_rebase left running instead of propagating past it, and reword
keeps its state file when an abort failed, so loom abort still has it. The
restore needs to ask whether a rebase is still on disk, so rebase_is_over
names the check rebase_abort_then_cleanup was spelling out inline.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

Summary by CodeRabbit

  • Bug Fixes

    • Staged changes now remain staged after branch creation, updates, drops, folds, rewords, swaps, and other rebase-based operations.
    • Staging is preserved when continuing after conflict resolution or aborting an operation.
    • If changes cannot be restored safely, they remain available for recovery instead of being lost.
  • Documentation

    • Updated command guides, conflict-resolution guidance, and specifications to explain staged-change preservation and recovery options.
  • Tests

    • Added coverage for staged files, new files, conflicts, aborts, and restoration failures.

git rebase --autostash replays its stash into the working tree only, so a
staged modification came back unstaged on success, not just on abort. Only
the abort path compensated, and drop, update and reword saved nothing at
all, so every rebasing command quietly unstaged the user's work.

Restore the saved patch on the RebaseOutcome::Completed arm and in every
after_continue handler too, through one helper, and hand over what cannot be
replayed rather than dropping it. Why it applies three-way against a
rehearsed copy of the index rather than resetting is in Spec 014 and on the
helper itself; the cost is a diff of the index per rebase, and a copy of it
plus two applies per restore.

Two recovery paths change with it: run_rebase_or_abort now aborts a rebase
its own run_rebase left running instead of propagating past it, and reword
keeps its state file when an abort failed, so loom abort still has it. The
restore needs to ask whether a rebase is still on disk, so rebase_is_over
names the check rebase_abort_then_cleanup was spelling out inline.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 90293a9f-9014-418d-8b3a-0f004cf14faf

📥 Commits

Reviewing files that changed from the base of the PR and between fa1dc16 and 7490eb6.

📒 Files selected for processing (36)
  • CLAUDE.md
  • docs/src/commands/branch.md
  • docs/src/commands/drop.md
  • docs/src/commands/fold.md
  • docs/src/commands/reword.md
  • docs/src/commands/swap.md
  • docs/src/commands/update.md
  • docs/src/guides/conflict-resolution.md
  • specs/003-reword.md
  • specs/004-weave.md
  • specs/007-fold.md
  • specs/008-drop.md
  • specs/010-update.md
  • specs/014-continue-abort.md
  • specs/015-swap.md
  • src/absorb.rs
  • src/branch/new_test.rs
  • src/commit.rs
  • src/core/transaction.rs
  • src/core/weave.rs
  • src/drop.rs
  • src/drop_test.rs
  • src/fold.rs
  • src/fold_test.rs
  • src/git/git_apply.rs
  • src/git/git_apply_test.rs
  • src/git/git_rebase.rs
  • src/git/mod.rs
  • src/reword.rs
  • src/reword_test.rs
  • src/split.rs
  • src/swap.rs
  • src/swap_test.rs
  • src/update.rs
  • src/update_test.rs
  • tests/integration/test_drop.sh

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The change preserves staged changes across rebase completion, continuation, abortion, and rollback paths. It adds centralized three-way restoration, recovery parking, command-handler wiring, specifications, documentation, and regression tests.

Changes

Staged preservation

Layer / File(s) Summary
Staging requirements and recovery rules
CLAUDE.md, docs/src/commands/*, docs/src/guides/conflict-resolution.md, specs/*
Specifications and documentation now define staged-state restoration, three-way recovery, continuation behavior, and patch fallback handling.
Git staged restoration primitives
src/git/git_apply.rs, src/git/git_apply_test.rs, src/git/git_rebase.rs, src/git/mod.rs
Git helpers restore staged patches through scratch-index three-way application, classify replay modes, detect rebase completion, and test recovery cases.
Rebase and rollback orchestration
src/core/transaction.rs, src/core/weave.rs
Rebase flows save staged patches, restore them after completion or abortion, park failures, and leave the index unchanged when a rebase did not start.
Command completion and continuation handlers
src/absorb.rs, src/commit.rs, src/drop.rs, src/reword.rs, src/swap.rs, src/update.rs, src/branch/new_test.rs, src/drop_test.rs, src/reword_test.rs, src/swap_test.rs, src/update_test.rs, src/split.rs, tests/integration/test_drop.sh
Command handlers receive rollback data and restore staged changes after successful and resumed operations. Regression tests cover staged modifications, staged new files, and conflict continuation.
Fold and move restoration paths
src/fold.rs, src/fold_test.rs
Fold and move variants use rollback-held staged patches across success, failure, abort, refusal, and continuation paths. Tests cover the supported fold and uncommit variants.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant UserCommand
  participant run_rebase_or_abort
  participant Git
  participant Rollback
  UserCommand->>run_rebase_or_abort: start rebase with saved staged patch
  run_rebase_or_abort->>Git: run rebase with autostash
  Git-->>run_rebase_or_abort: complete, stop, or fail
  run_rebase_or_abort->>Rollback: restore or park staged patch
  Rollback-->>UserCommand: return command result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: restoring staged changes when a rebase completes.
Docstring Coverage ✅ Passed Docstring coverage is 95.92% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 98 functions across 21 files. (15 skipped: …
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

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.

1 participant