@@ -103,7 +103,12 @@ func runCascade(cmd *cobra.Command, args []string) error {
103103 }
104104 }
105105
106- err = doCascadeWithState (g , cfg , branches , cascadeDryRunFlag , state .OperationCascade , false , false , false , nil , stashRef , worktrees , s )
106+ err = doCascadeWithState (g , cfg , branches , CascadeOptions {
107+ DryRun : cascadeDryRunFlag ,
108+ Operation : state .OperationCascade ,
109+ StashRef : stashRef ,
110+ Worktrees : worktrees ,
111+ }, s )
107112
108113 // Restore auto-stashed changes after operation (unless conflict, which saves stash in state)
109114 if stashRef != "" && ! errors .Is (err , ErrConflict ) {
@@ -116,12 +121,39 @@ func runCascade(cmd *cobra.Command, args []string) error {
116121 return err
117122}
118123
124+ // CascadeOptions configures the behaviour of doCascadeWithState.
125+ //
126+ // The submit-specific fields (UpdateOnly, Web, PushOnly, AllBranches) are
127+ // only meaningful when Operation is state.OperationSubmit; they are persisted
128+ // to cascade state so that the push/PR phases can be resumed after a conflict.
129+ type CascadeOptions struct {
130+ // DryRun prints what would be done without actually rebasing.
131+ DryRun bool
132+ // Operation is the type of operation being performed (state.OperationCascade
133+ // or state.OperationSubmit).
134+ Operation string
135+ // UpdateOnly skips creating new PRs; only existing PRs are updated.
136+ // Submit-only.
137+ UpdateOnly bool
138+ // Web opens PRs in the browser after creation/update. Submit-only.
139+ Web bool
140+ // PushOnly skips the PR creation/update phase entirely. Submit-only.
141+ PushOnly bool
142+ // AllBranches is the complete list of branch names being submitted, used
143+ // to rebuild the full set for push/PR phases after cascade completes.
144+ // Submit-only.
145+ AllBranches []string
146+ // StashRef is the commit hash of auto-stashed changes (if any), persisted
147+ // to state so they can be restored when the operation completes or is aborted.
148+ StashRef string
149+ // Worktrees maps branch names to linked worktree paths. When non-nil, branches
150+ // present in the map are rebased directly in their worktree directory instead
151+ // of being checked out in the main working tree.
152+ Worktrees map [string ]string
153+ }
154+
119155// doCascadeWithState performs cascade and saves state with the given operation type.
120- // allBranches is the complete list of branches for submit operations (used for push/PR after continue).
121- // stashRef is the commit hash of auto-stashed changes (if any), persisted to state on conflict.
122- // worktrees maps branch names to linked worktree paths. When non-nil, branches in
123- // the map are rebased directly in their worktree directory instead of being checked out.
124- func doCascadeWithState (g * git.Git , cfg * config.Config , branches []* tree.Node , dryRun bool , operation string , updateOnly , web , pushOnly bool , allBranches []string , stashRef string , worktrees map [string ]string , s * style.Style ) error {
156+ func doCascadeWithState (g * git.Git , cfg * config.Config , branches []* tree.Node , opts CascadeOptions , s * style.Style ) error {
125157 originalBranch , err := g .CurrentBranch ()
126158 if err != nil {
127159 return err
@@ -150,7 +182,7 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d
150182 // was rebased outside gh-stack the stored fork point would be stale;
151183 // keeping it current prevents a future --onto rebase from replaying
152184 // too many commits.
153- if ! dryRun {
185+ if ! opts . DryRun {
154186 parentTip , tipErr := g .GetTip (parent )
155187 if tipErr == nil {
156188 _ = cfg .SetForkPoint (b .Name , parentTip ) //nolint:errcheck // best effort
@@ -159,7 +191,7 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d
159191 continue
160192 }
161193
162- if dryRun {
194+ if opts . DryRun {
163195 fmt .Printf ("%s Would rebase %s onto %s\n " , s .Muted ("dry-run:" ), s .Branch (b .Name ), s .Branch (parent ))
164196 continue
165197 }
@@ -210,8 +242,8 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d
210242
211243 // Determine if this branch lives in a linked worktree
212244 wtPath := ""
213- if worktrees != nil {
214- wtPath = worktrees [b .Name ]
245+ if opts . Worktrees != nil {
246+ wtPath = opts . Worktrees [b .Name ]
215247 }
216248
217249 if useOnto {
@@ -259,13 +291,13 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d
259291 Current : b .Name ,
260292 Pending : remaining ,
261293 OriginalHead : originalHead ,
262- Operation : operation ,
263- UpdateOnly : updateOnly ,
264- Web : web ,
265- PushOnly : pushOnly ,
266- Branches : allBranches ,
267- StashRef : stashRef ,
268- Worktrees : worktrees ,
294+ Operation : opts . Operation ,
295+ UpdateOnly : opts . UpdateOnly ,
296+ Web : opts . Web ,
297+ PushOnly : opts . PushOnly ,
298+ Branches : opts . AllBranches ,
299+ StashRef : opts . StashRef ,
300+ Worktrees : opts . Worktrees ,
269301 }
270302 _ = state .Save (g .GetGitDir (), st ) //nolint:errcheck // best effort - user can recover manually
271303
@@ -274,7 +306,7 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d
274306 fmt .Printf ("Resolve conflicts in worktree: %s\n " , wtPath )
275307 }
276308 fmt .Printf ("Remaining branches: %v\n " , remaining )
277- if stashRef != "" {
309+ if opts . StashRef != "" {
278310 fmt .Println (s .Muted ("Note: Your uncommitted changes are stashed and will be restored when you continue or abort." ))
279311 }
280312 return ErrConflict
@@ -290,7 +322,7 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d
290322 }
291323
292324 // Return to original branch
293- if ! dryRun {
325+ if ! opts . DryRun {
294326 _ = g .Checkout (originalBranch ) //nolint:errcheck // best effort - cascade succeeded
295327 }
296328
0 commit comments