From 61471f3e254bfd4bb2209830a7c54046e9c2c53b Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Fri, 6 Feb 2026 13:25:26 -0800 Subject: [PATCH 1/2] docs(README): move link to ARCHITECTURE.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 39be382..05fca79 100644 --- a/README.md +++ b/README.md @@ -416,8 +416,6 @@ If you want the kitchen sink—stack navigation, branch surgery, a web UI, AI re - **Easier debugging.** You can inspect and repair state with `git config --edit` or a text editor. No need for `git cat-file` or `git log` on an internal ref. - **No state history.** **git-spice** gets a full audit log for free. **gh-stack** provides multi-level undo via separate snapshot files instead, which covers the common case (undoing the last operation) without the overhead. -See [ARCHITECTURE.md](ARCHITECTURE.md) for a detailed breakdown of **gh-stack**'s data storage approach. - ## Project Scope - **gh-stack** aims to be a minimal alternative to Graphite for those who do not need its full feature set @@ -437,6 +435,8 @@ make lint # Run linter make gh-install # Install as gh extension locally ``` +See [ARCHITECTURE.md](ARCHITECTURE.md) for a detailed breakdown of **gh-stack**'s data storage approach. + ## Acknowledgements - Inspired by [Graphite][]. From 938f1d24b77fd346bb5b3fdd1cf081937b277fe5 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Fri, 6 Feb 2026 13:27:51 -0800 Subject: [PATCH 2/2] feat: rename cascade command to restack, keep cascade as alias The `cascade` command is now `restack`, with `cascade` retained as a Cobra alias for backward compatibility. All user-facing strings (help text, output messages, error messages) and documentation updated accordingly. The `--no-cascade` flag on `sync` is now `--no-restack`. Internal identifiers (function names, `STACK_CASCADE_STATE`, `OperationCascade`, etc.) are intentionally unchanged. Co-authored-by: Cursor --- ARCHITECTURE.md | 16 +++++++-------- README.md | 50 +++++++++++++++++++++++----------------------- cmd/abort.go | 13 ++++++++---- cmd/cascade.go | 23 +++++++++++---------- cmd/continue.go | 4 ++-- cmd/submit.go | 10 +++++----- cmd/sync.go | 10 +++++----- cmd/undo.go | 4 ++-- e2e/README.md | 4 ++-- e2e/submit_test.go | 8 ++++---- e2e/undo_test.go | 4 ++-- 11 files changed, 76 insertions(+), 70 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 25d4731..5c014e9 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -86,14 +86,14 @@ When a multi-branch rebase is interrupted by a conflict, gh-stack saves the oper | `current` | Branch where the conflict occurred | | `pending` | Remaining branches to rebase | | `original_head` | HEAD before the operation started (for abort) | -| `operation` | `"cascade"` or `"submit"` | +| `operation` | `"cascade"` or `"submit"` (`"cascade"` is used by the `restack` command) | | `stash_ref` | Commit hash of auto-stashed uncommitted changes | | `branches` | Full branch list (submit only; used to rebuild the set for push/PR phases) | | `update_only`, `web`, `push_only` | Submit-specific flags preserved across continue | ### Cascade State Lifecycle -1. **Created** when a rebase conflict interrupts `cascade`, `submit`, or `sync`. +1. **Created** when a rebase conflict interrupts `restack`, `submit`, or `sync`. 2. **Removed** before `continue` resumes (will be recreated if another conflict occurs). 3. **Removed** on successful completion or `abort`. @@ -101,7 +101,7 @@ When a multi-branch rebase is interrupted by a conflict, gh-stack saves the oper This is an ephemeral, single-operation state file. It is not designed to survive beyond the operation that created it. -- **Single-operation scope.** Only one cascade/submit/sync can be in progress at a time. The code checks for this file and refuses to start a new operation if one exists. +- **Single-operation scope.** Only one restack/submit/sync can be in progress at a time. The code checks for this file and refuses to start a new operation if one exists. - **Best-effort persistence.** Save errors are ignored (`//nolint:errcheck`) because if we can't save state, the user can still recover manually by aborting the rebase and re-running the command. ## Undo Snapshots @@ -116,7 +116,7 @@ Before any destructive operation, gh-stack captures a snapshot of every affected { "timestamp": "2026-02-05T12:00:00Z", "operation": "cascade", - "command": "gh stack cascade", + "command": "gh stack restack", "original_head": "abc123...", "stash_ref": "", "branches": { @@ -133,7 +133,7 @@ Before any destructive operation, gh-stack captures a snapshot of every affected ### Snapshot Lifecycle -1. **Created** before destructive operations (`cascade`, `submit`, `sync`). +1. **Created** before destructive operations (`restack`, `submit`, `sync`). 2. **Used** by `undo`, which restores branch refs and config keys from the snapshot. 3. **Archived** to `done/` after a successful undo. 4. **Pruned** automatically: max 50 active snapshots and 50 archived. Oldest are removed first. @@ -153,7 +153,7 @@ flowchart TD init[init] create[create / adopt] submit[submit / link] - cascade[cascade / sync] + restack[restack / sync] undoCmd[undo] end @@ -166,8 +166,8 @@ flowchart TD init -->|set trunk| config create -->|set parent, fork point| config submit -->|set PR number| config - cascade -->|on conflict| state - cascade -->|before start| snapshots + restack -->|on conflict| state + restack -->|before start| snapshots undoCmd -->|restore from| snapshots undoCmd -->|restore| config ``` diff --git a/README.md b/README.md index 05fca79..d122eab 100644 --- a/README.md +++ b/README.md @@ -76,26 +76,26 @@ main Say we've made changes in `feature-auth`. To keep the stack in sync, we will need to rebase `feature-auth-tests` onto `feature-auth`. From branch `feature-auth`, execute: ```bash -gh stack cascade +gh stack restack ``` -If you run into conflicts, resolve them and run `gh stack continue` to resume the cascade (or `gh stack abort` to cancel). Once complete, your local stacks will be in sync. _They won't yet be pushed to the remote repository._ +If you run into conflicts, resolve them and run `gh stack continue` to resume the restack (or `gh stack abort` to cancel). Once complete, your local stacks will be in sync. _They won't yet be pushed to the remote repository._ #### Scenario 2: Changes in the local trunk Maybe we pulled down `main` and it has new commits. We'll use the same strategy as above, but this time from the `main` branch: ```bash -gh stack cascade +gh stack restack ``` > [!NOTE] > -> Since `main` (the trunk) is the parent of every stack, `gh stack cascade` will naturally cascade _all_ stacks. +> Since `main` (the trunk) is the parent of every stack, `gh stack restack` will naturally restack _all_ stacks. #### Scenario 3: Upstream changes -Say `feature-auth` has been merged into the remote `main`. We now need to cascade the changes, but also retarget `feature-auth-tests` to `main` from `feature-auth`. You'll want to run: +Say `feature-auth` has been merged into the remote `main`. We now need to restack the changes, but also retarget `feature-auth-tests` to `main` from `feature-auth`. You'll want to run: ```bash gh stack sync @@ -108,7 +108,7 @@ This will: 3. Detect merged PRs 4. Clean up merged branches 5. Retarget orphaned children to trunk -6. Cascade all branches +6. Restack all branches What it _won't_ do is push back up to the remote; see the [next section](#creating--updating-prs) for that. @@ -124,7 +124,7 @@ Whenever you need to push these branches again, or update the PRs, you can run ` > [!TIP] > -> `gh stack submit` does everything `gh stack cascade` does, and then some. Generally, if you want to make local mid-stack changes _without_ pushing to the remote, you'll want `gh stack cascade`; otherwise just use `gh stack submit`. +> `gh stack submit` does everything `gh stack restack` does, and then some. Generally, if you want to make local mid-stack changes _without_ pushing to the remote, you'll want `gh stack restack`; otherwise just use `gh stack submit`. ## Commands @@ -137,11 +137,11 @@ Whenever you need to push these branches again, or update the PRs, you can run ` | `orphan` | Stop tracking a branch | | `link` | Associate PR number with branch | | `unlink` | Remove PR association | -| `submit` | Cascade, push, and create/update PRs in one command | -| `cascade` | Rebase branch and descendants onto parents | +| `submit` | Restack, push, and create/update PRs in one command | +| `restack` | Rebase branch and descendants onto parents | | `continue` | Resume operation after conflict resolution | | `abort` | Cancel in-progress operation | -| `sync` | Full sync: fetch, cleanup merged PRs, cascade all | +| `sync` | Full sync: fetch, cleanup merged PRs, restack all | | `undo` | Undo the last destructive operation | ## Command Reference @@ -254,11 +254,11 @@ The PR itself is not affected; this only removes the local tracking. ### submit -Cascade, push, and create/update PRs for current branch and descendants. +Restack, push, and create/update PRs for current branch and descendants. This is the primary workflow command. It performs three phases: -1. **Cascade**: Rebase current branch and descendants onto their parents +1. **Restack**: Rebase current branch and descendants onto their parents 2. **Push**: Force-push all affected branches (using `--force-with-lease`) 3. **PR**: Create PRs for branches without them; update PR bases for existing PRs @@ -273,38 +273,38 @@ If a rebase conflict occurs, resolve it and run `gh stack continue`. | `--dry-run` | Show what would happen without doing it | | `--current-only` | Only submit the current branch, not descendants | | `--update-only` | Only update existing PRs, don't create new ones | -| `--push-only` | Skip PR creation/update, only cascade and push | +| `--push-only` | Skip PR creation/update, only restack and push | -### cascade +### restack -Rebase the current branch and its descendants onto their parents. +Rebase the current branch and its descendants onto their parents. Aliased as `cascade`. Use this when you've made local changes and want to keep your stack in sync without pushing or creating PRs. For a full submit workflow, use `gh stack submit` instead. If a rebase conflict occurs, resolve it and run `gh stack continue`. -#### cascade Flags +#### restack Flags -| Flag | Description | -| ----------- | -------------------------------------------- | -| `--only` | Only cascade current branch, not descendants | -| `--dry-run` | Show what would be done | +| Flag | Description | +| ----------- | --------------------------------------------- | +| `--only` | Only restack current branch, not descendants | +| `--dry-run` | Show what would be done | ### continue -Continue a cascade or submit operation after resolving rebase conflicts. +Continue a restack or submit operation after resolving rebase conflicts. After resolving conflicts and staging the changes, run this command to resume the operation. ### abort -Abort a cascade or submit operation in progress. +Abort a restack or submit operation in progress. This aborts any in-progress rebase and cleans up the operation state. Your branches will be left in their pre-operation state. ### sync -Full sync: fetch from origin, detect merged PRs, clean up merged branches, retarget orphaned children, and cascade all branches. +Full sync: fetch from origin, detect merged PRs, clean up merged branches, retarget orphaned children, and restack all branches. This is the command to run when upstream changes have occurred (e.g., a PR in your stack was merged). It handles the bookkeeping of updating your local stack to match remote state. @@ -312,12 +312,12 @@ This is the command to run when upstream changes have occurred (e.g., a PR in yo | Flag | Description | | -------------- | ----------------------- | -| `--no-cascade` | Skip cascading branches | +| `--no-restack` | Skip restacking branches | | `--dry-run` | Show what would be done | ### undo -Undo the last destructive operation (cascade, submit, or sync) by restoring branches to their pre-operation state. +Undo the last destructive operation (restack, submit, or sync) by restoring branches to their pre-operation state. Before any destructive operation, gh-stack automatically captures a snapshot of affected branches. If something goes wrong or you change your mind, `undo` restores: diff --git a/cmd/abort.go b/cmd/abort.go index 8d130c3..6ac0cad 100644 --- a/cmd/abort.go +++ b/cmd/abort.go @@ -4,6 +4,7 @@ package cmd import ( "fmt" "os" + "strings" "github.com/boneskull/gh-stack/internal/git" "github.com/boneskull/gh-stack/internal/state" @@ -13,8 +14,8 @@ import ( var abortCmd = &cobra.Command{ Use: "abort", - Short: "Abort a cascade in progress", - Long: `Abort a cascade operation and restore the original state.`, + Short: "Abort an operation in progress", + Long: `Abort a restack or submit operation and restore the original state.`, RunE: runAbort, } @@ -35,7 +36,7 @@ func runAbort(cmd *cobra.Command, args []string) error { // Check if cascade in progress st, err := state.Load(g.GetGitDir()) if err != nil { - return fmt.Errorf("no cascade in progress") + return fmt.Errorf("no operation in progress") } // Abort rebase if in progress @@ -57,6 +58,10 @@ func runAbort(cmd *cobra.Command, args []string) error { } } - fmt.Printf("%s Cascade aborted. Original HEAD was %s\n", s.WarningIcon(), st.OriginalHead) + opName := st.Operation + if opName == "" { + opName = "Operation" + } + fmt.Printf("%s %s aborted. Original HEAD was %s\n", s.WarningIcon(), strings.ToUpper(opName[:1])+opName[1:], st.OriginalHead) return nil } diff --git a/cmd/cascade.go b/cmd/cascade.go index d57f742..6454378 100644 --- a/cmd/cascade.go +++ b/cmd/cascade.go @@ -19,10 +19,11 @@ import ( var ErrConflict = errors.New("rebase conflict: resolve and run 'gh stack continue', or 'gh stack abort'") var cascadeCmd = &cobra.Command{ - Use: "cascade", - Short: "Rebase current branch and descendants onto their parents", - Long: `Rebase the current branch onto its parent, then recursively cascade to descendants.`, - RunE: runCascade, + Use: "restack", + Aliases: []string{"cascade"}, + Short: "Rebase current branch and descendants onto their parents", + Long: `Rebase the current branch onto its parent, then recursively restack descendants.`, + RunE: runCascade, } var ( @@ -31,7 +32,7 @@ var ( ) func init() { - cascadeCmd.Flags().BoolVar(&cascadeOnlyFlag, "only", false, "only cascade current branch, not descendants") + cascadeCmd.Flags().BoolVar(&cascadeOnlyFlag, "only", false, "only restack current branch, not descendants") cascadeCmd.Flags().BoolVar(&cascadeDryRunFlag, "dry-run", false, "show what would be done") rootCmd.AddCommand(cascadeCmd) } @@ -53,7 +54,7 @@ func runCascade(cmd *cobra.Command, args []string) error { // Check if cascade already in progress if state.Exists(g.GetGitDir()) { - return fmt.Errorf("cascade already in progress; use 'gh stack continue' or 'gh stack abort'") + return fmt.Errorf("operation already in progress; use 'gh stack continue' or 'gh stack abort'") } currentBranch, err := g.CurrentBranch() @@ -84,7 +85,7 @@ func runCascade(cmd *cobra.Command, args []string) error { var stashRef string if !cascadeDryRunFlag { var saveErr error - stashRef, saveErr = saveUndoSnapshot(g, cfg, branches, nil, "cascade", "gh stack cascade", s) + stashRef, saveErr = saveUndoSnapshot(g, cfg, branches, nil, "cascade", "gh stack restack", s) if saveErr != nil { fmt.Printf("%s could not save undo state: %v\n", s.WarningIcon(), saveErr) } @@ -129,7 +130,7 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d } if !needsRebase { - fmt.Printf("Cascading %s... %s\n", s.Branch(b.Name), s.Muted("already up to date")) + fmt.Printf("Restacking %s... %s\n", s.Branch(b.Name), s.Muted("already up to date")) continue } @@ -153,9 +154,9 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d } if useOnto { - fmt.Printf("Cascading %s onto %s %s...\n", s.Branch(b.Name), s.Branch(parent), s.Muted("(using fork point)")) + fmt.Printf("Restacking %s onto %s %s...\n", s.Branch(b.Name), s.Branch(parent), s.Muted("(using fork point)")) } else { - fmt.Printf("Cascading %s onto %s...\n", s.Branch(b.Name), s.Branch(parent)) + fmt.Printf("Restacking %s onto %s...\n", s.Branch(b.Name), s.Branch(parent)) } // Checkout and rebase @@ -198,7 +199,7 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d return ErrConflict } - fmt.Printf("Cascading %s... %s\n", s.Branch(b.Name), s.Success("ok")) + fmt.Printf("Restacking %s... %s\n", s.Branch(b.Name), s.Success("ok")) // Update fork point to current parent tip parentTip, tipErr := g.GetTip(parent) diff --git a/cmd/continue.go b/cmd/continue.go index d853e16..7abeb70 100644 --- a/cmd/continue.go +++ b/cmd/continue.go @@ -16,7 +16,7 @@ import ( var continueCmd = &cobra.Command{ Use: "continue", Short: "Continue an operation after resolving conflicts", - Long: `Continue a cascade or submit operation after resolving rebase conflicts.`, + Long: `Continue a restack or submit operation after resolving rebase conflicts.`, RunE: runContinue, } @@ -133,6 +133,6 @@ func runContinue(cmd *cobra.Command, args []string) error { } } - fmt.Println(s.SuccessMessage("Cascade complete!")) + fmt.Println(s.SuccessMessage("Restack complete!")) return nil } diff --git a/cmd/submit.go b/cmd/submit.go index e2a2671..45d6097 100644 --- a/cmd/submit.go +++ b/cmd/submit.go @@ -19,12 +19,12 @@ import ( var submitCmd = &cobra.Command{ Use: "submit", - Short: "Cascade, push, and create/update PRs for current branch and descendants", + Short: "Restack, push, and create/update PRs for current branch and descendants", Long: `Submit rebases the current branch and its descendants onto their parents, pushes all affected branches, and creates or updates pull requests. This is the typical workflow command after making changes in a stack: -1. Cascade: rebase current branch + descendants onto their parents +1. Restack: rebase current branch + descendants onto their parents 2. Push: force-push all affected branches (with --force-with-lease) 3. PR: create PRs for branches without them, update PR bases for those that have them @@ -45,7 +45,7 @@ func init() { submitCmd.Flags().BoolVar(&submitDryRunFlag, "dry-run", false, "show what would be done without doing it") submitCmd.Flags().BoolVar(&submitCurrentOnlyFlag, "current-only", false, "only submit current branch, not descendants") submitCmd.Flags().BoolVar(&submitUpdateOnlyFlag, "update-only", false, "only update existing PRs, don't create new ones") - submitCmd.Flags().BoolVar(&submitPushOnlyFlag, "push-only", false, "skip PR creation/update, only cascade and push") + submitCmd.Flags().BoolVar(&submitPushOnlyFlag, "push-only", false, "skip PR creation/update, only restack and push") submitCmd.Flags().BoolVarP(&submitYesFlag, "yes", "y", false, "skip interactive prompts and use auto-generated title/description for PRs") submitCmd.Flags().BoolVarP(&submitWebFlag, "web", "w", false, "open created/updated PRs in web browser") rootCmd.AddCommand(submitCmd) @@ -135,8 +135,8 @@ func runSubmit(cmd *cobra.Command, args []string) error { } } - // Phase 1: Cascade - fmt.Println(s.Bold("=== Phase 1: Cascade ===")) + // Phase 1: Restack + fmt.Println(s.Bold("=== Phase 1: Restack ===")) if cascadeErr := doCascadeWithState(g, cfg, branches, submitDryRunFlag, state.OperationSubmit, submitUpdateOnlyFlag, submitWebFlag, submitPushOnlyFlag, branchNames, stashRef, s); cascadeErr != nil { // Stash is saved in state for conflicts; restore on other errors if cascadeErr != ErrConflict && stashRef != "" { diff --git a/cmd/sync.go b/cmd/sync.go index 1284bf6..7631f8b 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -17,8 +17,8 @@ import ( var syncCmd = &cobra.Command{ Use: "sync", - Short: "Fetch, detect merged PRs, retarget orphaned branches, cascade all", - Long: `Fetch from origin, detect merged PRs, retarget orphaned branches to trunk, and cascade all branches.`, + Short: "Fetch, detect merged PRs, retarget orphaned branches, restack all", + Long: `Fetch from origin, detect merged PRs, retarget orphaned branches to trunk, and restack all branches.`, RunE: runSync, } @@ -28,7 +28,7 @@ var ( ) func init() { - syncCmd.Flags().BoolVar(&syncNoCascadeFlag, "no-cascade", false, "skip cascading branches") + syncCmd.Flags().BoolVar(&syncNoCascadeFlag, "no-restack", false, "skip restacking branches") syncCmd.Flags().BoolVar(&syncDryRunFlag, "dry-run", false, "show what would be done") rootCmd.AddCommand(syncCmd) } @@ -311,7 +311,7 @@ func runSync(cmd *cobra.Command, args []string) error { } fmt.Printf("Rebasing %s onto %s (from fork point %s)...\n", s.Branch(rt.childName), s.Branch(trunk), displayForkPoint) if rebaseErr := g.RebaseOnto(trunk, rt.forkPoint, rt.childName); rebaseErr != nil { - fmt.Printf("%s --onto rebase failed, will try normal cascade: %v\n", s.WarningIcon(), rebaseErr) + fmt.Printf("%s --onto rebase failed, will try normal restack: %v\n", s.WarningIcon(), rebaseErr) // Don't return error - let cascade try } else { fmt.Printf("%s Rebased %s successfully\n", s.SuccessIcon(), s.Branch(rt.childName)) @@ -332,7 +332,7 @@ func runSync(cmd *cobra.Command, args []string) error { // Cascade all (if not disabled) if !syncNoCascadeFlag { - fmt.Println(s.Bold("\nCascading all branches...")) + fmt.Println(s.Bold("\nRestacking all branches...")) // Rebuild tree after modifications root, err = tree.Build(cfg) if err != nil { diff --git a/cmd/undo.go b/cmd/undo.go index 5b6758f..e9cd930 100644 --- a/cmd/undo.go +++ b/cmd/undo.go @@ -18,7 +18,7 @@ import ( var undoCmd = &cobra.Command{ Use: "undo", Short: "Undo the last destructive operation", - Long: `Undo the last cascade, submit, or sync operation by restoring branches + Long: `Undo the last restack, submit, or sync operation by restoring branches to their previous state. This includes: - Resetting branch refs to their pre-operation SHAs @@ -54,7 +54,7 @@ func runUndo(cmd *cobra.Command, args []string) error { // Check if a cascade/submit is in progress if state.Exists(gitDir) { - return errors.New("cannot undo while a cascade/submit is in progress; run 'gh stack continue' or 'gh stack abort' first") + return errors.New("cannot undo while an operation is in progress; run 'gh stack continue' or 'gh stack abort' first") } // Check if a rebase is in progress diff --git a/e2e/README.md b/e2e/README.md index 7ba08f2..42f8653 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -30,7 +30,7 @@ make test - `scenario_helpers_test.go` - Conflict and remote simulation helpers - `smoke_test.go` - Basic smoke test - `init_create_test.go` - Init and create command tests -- `cascade_test.go` - Cascade tests including conflict recovery +- `cascade_test.go` - Restack tests including conflict recovery - `adopt_orphan_test.go` - Adopt and orphan command tests - `push_test.go` - Push command tests - `error_cases_test.go` - Error handling tests @@ -58,7 +58,7 @@ make test | Category | Description | |----------|-------------| -| Happy path | Normal workflows (init, create, cascade, push) | +| Happy path | Normal workflows (init, create, restack, push) | | Error recovery | Conflicts, abort/continue, dirty working tree | | Chaos tests | Manual git operations, remote sync edge cases | diff --git a/e2e/submit_test.go b/e2e/submit_test.go index c58612b..7ff84d6 100644 --- a/e2e/submit_test.go +++ b/e2e/submit_test.go @@ -16,8 +16,8 @@ func TestSubmitDryRun(t *testing.T) { result := env.MustRun("submit", "--dry-run") // Should show all three phases - if !strings.Contains(result.Stdout, "Phase 1: Cascade") { - t.Error("expected cascade phase output") + if !strings.Contains(result.Stdout, "Phase 1: Restack") { + t.Error("expected restack phase output") } if !strings.Contains(result.Stdout, "Phase 2: Push") { t.Error("expected push phase output") @@ -265,8 +265,8 @@ func TestSubmitPushOnlyDryRun(t *testing.T) { result := env.MustRun("submit", "--dry-run", "--push-only") // Should show all three phases - if !strings.Contains(result.Stdout, "Phase 1: Cascade") { - t.Error("expected cascade phase output") + if !strings.Contains(result.Stdout, "Phase 1: Restack") { + t.Error("expected restack phase output") } if !strings.Contains(result.Stdout, "Phase 2: Push") { t.Error("expected push phase output") diff --git a/e2e/undo_test.go b/e2e/undo_test.go index 1296953..9223b05 100644 --- a/e2e/undo_test.go +++ b/e2e/undo_test.go @@ -263,8 +263,8 @@ func TestUndoBlockedDuringCascade(t *testing.T) { if result.Success() { t.Error("undo should fail during cascade in progress") } - if !result.ContainsStdout("cascade/submit is in progress") && !result.ContainsStderr("cascade/submit is in progress") { - t.Errorf("expected message about cascade in progress, got stdout: %s, stderr: %s", result.Stdout, result.Stderr) + if !result.ContainsStdout("operation is in progress") && !result.ContainsStderr("operation is in progress") { + t.Errorf("expected message about operation in progress, got stdout: %s, stderr: %s", result.Stdout, result.Stderr) } // Abort the cascade