@@ -78,13 +78,26 @@ func runCascade(cmd *cobra.Command, args []string) error {
7878 }
7979
8080 // Save undo snapshot (unless dry-run)
81+ var stashRef string
8182 if ! cascadeDryRunFlag {
82- if err := saveUndoSnapshot (g , cfg , branches , nil , "cascade" , "gh stack cascade" ); err != nil {
83- fmt .Printf ("Warning: could not save undo state: %v\n " , err )
83+ var saveErr error
84+ stashRef , saveErr = saveUndoSnapshot (g , cfg , branches , nil , "cascade" , "gh stack cascade" )
85+ if saveErr != nil {
86+ fmt .Printf ("Warning: could not save undo state: %v\n " , saveErr )
8487 }
8588 }
8689
87- return doCascade (g , cfg , branches , cascadeDryRunFlag )
90+ err = doCascade (g , cfg , branches , cascadeDryRunFlag )
91+
92+ // Restore auto-stashed changes after successful operation
93+ if err == nil && stashRef != "" {
94+ fmt .Println ("Restoring auto-stashed changes..." )
95+ if popErr := g .StashPop (stashRef ); popErr != nil {
96+ fmt .Printf ("Warning: could not restore stashed changes (commit %s): %v\n " , stashRef [:7 ], popErr )
97+ }
98+ }
99+
100+ return err
88101}
89102
90103func doCascade (g * git.Git , cfg * config.Config , branches []* tree.Node , dryRun bool ) error {
@@ -201,27 +214,30 @@ func doCascadeWithState(g *git.Git, cfg *config.Config, branches []*tree.Node, d
201214// It auto-stashes any uncommitted changes if the working tree is dirty.
202215// branches: branches that will be modified (rebased)
203216// deletedBranches: branches that will be deleted (for sync)
204- func saveUndoSnapshot (g * git.Git , cfg * config.Config , branches []* tree.Node , deletedBranches []* tree.Node , operation , command string ) error {
217+ // Returns the stash ref (commit hash) if changes were stashed, empty string otherwise.
218+ func saveUndoSnapshot (g * git.Git , cfg * config.Config , branches []* tree.Node , deletedBranches []* tree.Node , operation , command string ) (string , error ) {
205219 gitDir := g .GetGitDir ()
206220
207221 // Get current branch for original head
208222 currentBranch , err := g .CurrentBranch ()
209223 if err != nil {
210- return err
224+ return "" , err
211225 }
212226
213227 // Create snapshot
214228 snapshot := undo .NewSnapshot (operation , command , currentBranch )
215229
216230 // Auto-stash if dirty
231+ var stashRef string
217232 dirty , err := g .IsDirty ()
218233 if err != nil {
219- return err
234+ return "" , err
220235 }
221236 if dirty {
222- stashRef , stashErr := g .Stash ("gh-stack auto-stash before " + operation )
237+ var stashErr error
238+ stashRef , stashErr = g .Stash ("gh-stack auto-stash before " + operation )
223239 if stashErr != nil {
224- return fmt .Errorf ("failed to stash changes: %w" , stashErr )
240+ return "" , fmt .Errorf ("failed to stash changes: %w" , stashErr )
225241 }
226242 if stashRef != "" {
227243 snapshot .StashRef = stashRef
@@ -231,52 +247,58 @@ func saveUndoSnapshot(g *git.Git, cfg *config.Config, branches []*tree.Node, del
231247
232248 // Capture state of branches that will be modified
233249 for _ , node := range branches {
234- bs , err := captureBranchState (g , cfg , node .Name )
235- if err != nil {
250+ bs , captureErr := captureBranchState (g , cfg , node .Name )
251+ if captureErr != nil {
236252 // Non-fatal: log warning and continue
237- fmt .Printf ("Warning: could not capture state for %s: %v\n " , node .Name , err )
253+ fmt .Printf ("Warning: could not capture state for %s: %v\n " , node .Name , captureErr )
238254 continue
239255 }
240256 snapshot .Branches [node .Name ] = bs
241257 }
242258
243259 // Capture state of branches that will be deleted
244260 for _ , node := range deletedBranches {
245- bs , err := captureBranchState (g , cfg , node .Name )
246- if err != nil {
247- fmt .Printf ("Warning: could not capture state for deleted branch %s: %v\n " , node .Name , err )
261+ bs , captureErr := captureBranchState (g , cfg , node .Name )
262+ if captureErr != nil {
263+ fmt .Printf ("Warning: could not capture state for deleted branch %s: %v\n " , node .Name , captureErr )
248264 continue
249265 }
250266 snapshot .DeletedBranches [node .Name ] = bs
251267 }
252268
253269 // Save snapshot
254- return undo .Save (gitDir , snapshot )
270+ if saveErr := undo .Save (gitDir , snapshot ); saveErr != nil {
271+ return "" , saveErr
272+ }
273+ return stashRef , nil
255274}
256275
257276// saveUndoSnapshotByName is like saveUndoSnapshot but takes branch names instead of tree nodes.
258277// Useful for sync where we don't always have tree nodes.
259- func saveUndoSnapshotByName (g * git.Git , cfg * config.Config , branchNames []string , deletedBranchNames []string , operation , command string ) error {
278+ // Returns the stash ref (commit hash) if changes were stashed, empty string otherwise.
279+ func saveUndoSnapshotByName (g * git.Git , cfg * config.Config , branchNames []string , deletedBranchNames []string , operation , command string ) (string , error ) {
260280 gitDir := g .GetGitDir ()
261281
262282 // Get current branch for original head
263283 currentBranch , err := g .CurrentBranch ()
264284 if err != nil {
265- return err
285+ return "" , err
266286 }
267287
268288 // Create snapshot
269289 snapshot := undo .NewSnapshot (operation , command , currentBranch )
270290
271291 // Auto-stash if dirty
292+ var stashRef string
272293 dirty , err := g .IsDirty ()
273294 if err != nil {
274- return err
295+ return "" , err
275296 }
276297 if dirty {
277- stashRef , stashErr := g .Stash ("gh-stack auto-stash before " + operation )
298+ var stashErr error
299+ stashRef , stashErr = g .Stash ("gh-stack auto-stash before " + operation )
278300 if stashErr != nil {
279- return fmt .Errorf ("failed to stash changes: %w" , stashErr )
301+ return "" , fmt .Errorf ("failed to stash changes: %w" , stashErr )
280302 }
281303 if stashRef != "" {
282304 snapshot .StashRef = stashRef
@@ -286,26 +308,29 @@ func saveUndoSnapshotByName(g *git.Git, cfg *config.Config, branchNames []string
286308
287309 // Capture state of branches that will be modified
288310 for _ , name := range branchNames {
289- bs , err := captureBranchState (g , cfg , name )
290- if err != nil {
291- fmt .Printf ("Warning: could not capture state for %s: %v\n " , name , err )
311+ bs , captureErr := captureBranchState (g , cfg , name )
312+ if captureErr != nil {
313+ fmt .Printf ("Warning: could not capture state for %s: %v\n " , name , captureErr )
292314 continue
293315 }
294316 snapshot .Branches [name ] = bs
295317 }
296318
297319 // Capture state of branches that will be deleted
298320 for _ , name := range deletedBranchNames {
299- bs , err := captureBranchState (g , cfg , name )
300- if err != nil {
301- fmt .Printf ("Warning: could not capture state for deleted branch %s: %v\n " , name , err )
321+ bs , captureErr := captureBranchState (g , cfg , name )
322+ if captureErr != nil {
323+ fmt .Printf ("Warning: could not capture state for deleted branch %s: %v\n " , name , captureErr )
302324 continue
303325 }
304326 snapshot .DeletedBranches [name ] = bs
305327 }
306328
307329 // Save snapshot
308- return undo .Save (gitDir , snapshot )
330+ if saveErr := undo .Save (gitDir , snapshot ); saveErr != nil {
331+ return "" , saveErr
332+ }
333+ return stashRef , nil
309334}
310335
311336// captureBranchState captures the current state of a single branch.
0 commit comments