swtich to nearest surviving branch after modify#105
Open
skarim wants to merge 3 commits into
Open
Conversation
1fdd772 to
d522c91
Compare
f7e7a80 to
f633f33
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves gh stack modify UX by choosing a sensible post-modify checkout branch when the user’s original branch is no longer part of the stack (dropped/folded/renamed), instead of always restoring the original branch.
Changes:
- Add
resolveCheckoutBranch(plus snapshot-neighbor helpers) to determine the best branch to check out after modify. - Use the resolver in both
ApplyPlanandContinueApply, and print a message when switching away from the original branch. - Add unit tests for branch resolution and integration tests asserting final checkout behavior for drop/fold-down/rename scenarios.
Show a summary per file
| File | Description |
|---|---|
| internal/modify/apply.go | Adds resolver logic and uses it in ApplyPlan/ContinueApply to avoid landing on an orphaned branch. |
| internal/modify/apply_test.go | Adds unit + integration tests covering post-modify checkout resolution. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (2)
internal/modify/apply.go:535
- resolveCheckoutBranch treats only stack.Branches as “in stack”; if the user started on the trunk branch (e.g. "main"), s.IndexOf returns -1 and the function may incorrectly switch them to the topmost branch. Use Stack.Contains (which includes trunk) for the quick-exit check.
// Check if the original branch is still in the stack — quick exit.
if s.IndexOf(originalBranch) >= 0 {
return originalBranch
}
internal/modify/apply.go:571
- Branch resolution for fold/drop uses snapshot neighbor names and checks them directly against the post-modify stack. If a neighboring branch was renamed in the same modify operation (e.g. fold B down into A while also renaming A→new-A), the neighbor lookup will miss and resolution can fall back to an unrelated branch. Consider applying rename actions from the plan to candidate neighbor names before checking s.IndexOf / returning the target.
case "fold_down":
// Fold-down merges into the branch below in the original order.
if target := adjacentSnapshotBranch(snapshot, originalBranch, -1); target != "" {
if s.IndexOf(target) >= 0 {
return target
}
}
case "fold_up":
// Fold-up merges into the branch above in the original order.
if target := adjacentSnapshotBranch(snapshot, originalBranch, +1); target != "" {
if s.IndexOf(target) >= 0 {
return target
}
}
case "drop":
// Prefer the branch that was directly above in the original order,
// then fall back to the one below.
if above := nearestSurvivingBranch(snapshot, originalBranch, s); above != "" {
return above
}
}
- Files reviewed: 2/2 changed files
- Comments generated: 3
f633f33 to
d7f7cab
Compare
4f79dfe to
3ac2962
Compare
2609d7f to
12decbf
Compare
3ac2962 to
ae84c7d
Compare
After `gh stack modify` applies changes, the user may end up on an
orphaned branch that is no longer part of the stack — for example, if
their checked-out branch was dropped, folded into another branch, or
renamed. Previously, the code blindly restored the original branch
regardless of whether it still existed in the stack.
Add a `resolveCheckoutBranch` helper that inspects the modify plan and
the post-modify stack to determine the best branch to check out:
1. Still in stack → keep the original branch (no-op)
2. Renamed → check out the new name
3. Folded down → check out the fold target (branch below)
4. Folded up → check out the fold target (branch above)
5. Dropped → check out the nearest surviving neighbor
(prefer above, fall back to below)
6. Fallback → topmost branch in the stack
Both `ApplyPlan` and `ContinueApply` (the `--continue` path) now use
this helper instead of unconditionally restoring the original branch.
When the resolved branch differs from the original, a message is
printed so the user knows they've been switched.
The resolution uses the pre-modify snapshot (already persisted in the
state file) to determine original adjacency, so it works correctly even
when multiple branches are removed in the same operation.
Includes 12 new tests:
- 9 unit tests for resolveCheckoutBranch covering all action types,
edge cases (topmost dropped, multiple drops, empty stack), and
the fallback path
- 3 integration tests verifying ApplyPlan checks out the correct
branch after drop, fold-down, and rename operations
12decbf to
f9fbd25
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
After
gh stack modifyapplies changes, the user may end up on anorphaned branch that is no longer part of the stack — for example, if
their checked-out branch was dropped, folded into another branch, or
renamed. Previously, the code blindly restored the original branch
regardless of whether it still existed in the stack.
Add a
resolveCheckoutBranchhelper that inspects the modify plan andthe post-modify stack to determine the best branch to check out:
(prefer above, fall back to below)
Both
ApplyPlanandContinueApply(the--continuepath) now usethis helper instead of unconditionally restoring the original branch.
When the resolved branch differs from the original, a message is
printed so the user knows they've been switched.
The resolution uses the pre-modify snapshot (already persisted in the
state file) to determine original adjacency, so it works correctly even
when multiple branches are removed in the same operation.
Includes 12 new tests:
edge cases (topmost dropped, multiple drops, empty stack), and
the fallback path
branch after drop, fold-down, and rename operations
Stack created with GitHub Stacks CLI • Give Feedback 💬