-
Notifications
You must be signed in to change notification settings - Fork 26
Comparing changes
Open a pull request
base repository: github/gh-stack
base: v0.0.6
head repository: github/gh-stack
compare: v0.0.7
- 9 commits
- 61 files changed
- 5 contributors
Commits on Jun 15, 2026
-
Bump js-yaml in /docs in the npm_and_yarn group across 1 directory (#130
) Bumps the npm_and_yarn group with 1 update in the /docs directory: [js-yaml](https://github.com/nodeca/js-yaml). Updates `js-yaml` from 4.1.1 to 4.2.0 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/commits) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.2.0 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 84d160b - Browse repository at this point
Copy the full SHA 84d160bView commit details
Commits on Jun 17, 2026
-
Add
AGENTS.mdandcopilot-instructions.mdfor AI agent onboarding (……#133) * Add AGENTS.md and copilot-instructions.md for AI agent onboarding Add two complementary instruction files so AI coding agents can work effectively in this repository without re-discovering conventions: - AGENTS.md (7K chars): agent-agnostic open standard with full project structure, build/test commands, coding patterns, testing conventions, error handling, key interfaces, and non-obvious gotchas. - .github/copilot-instructions.md (2K chars): concise Copilot-specific instructions under the 4K code review limit, covering the essentials and referencing AGENTS.md for full details. Closes #132 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: update cmd to generate an executable binary Co-authored-by: Sameen Karim <skarim@github.com> * fix: update cmd to get the build output as an exec binary Co-authored-by: Sameen Karim <skarim@github.com> * Fix build command and errors.As usage per review feedback - go build ./... compiles but does not produce a binary. Changed to go build -o gh-stack . which actually outputs the executable. - errors.As(err, &ExitError{}) panics at runtime because the value type ExitError does not satisfy the error interface (only *ExitError does). Updated to the correct two-line pattern matching cmd/root.go. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Sameen Karim <skarim@github.com>
Configuration menu - View commit details
-
Copy full SHA for 4759126 - Browse repository at this point
Copy the full SHA 4759126View commit details
Commits on Jun 19, 2026
-
Unstack Updates: preflight PR eligibility before delete and improve A…
…PI errors (#136) * unstack: preflight PR eligibility before delete and improve API errors.Block unstack delete only when all PRs in the stack are ineligible * Update cmd/unstack.go Co-authored-by: Sameen Karim <skarim@github.com> * remove cfg and update help text --------- Co-authored-by: Sameen Karim <skarim@github.com>
Configuration menu - View commit details
-
Copy full SHA for 67d118f - Browse repository at this point
Copy the full SHA 67d118fView commit details
Commits on Jun 30, 2026
-
Redesign TUI shared header and embed the GitHub logo as an image (#143)
* Redesign the shared header and embed the GitHub logo as an image Rework the shared gh-stack header (used by `view` and `modify`, and reused by `submit` later in this stack) for a cleaner, more responsive look, and replace the braille/ASCII Invertocat with a real image of the GitHub mark. - Logo: embed the Invertocat PNG with go:embed and draw it via an inline- image protocol (kitty or iTerm2). It is image-or-nothing: when no protocol is available, stdout is not a TTY, or we are inside tmux/screen, no logo is drawn and the text falls back to the normal left padding. Detection is environment-based and cached so it never blocks the TUI, and a fixed kitty image id lets the header clear or replace the logo in place instead of leaving copies behind. - Layout: place the logo in the top-left corner beside the title and version, with the stack-info lines left-aligned beneath it on the same left margin. Size the box to its content for each view so there is no trailing empty row. - Responsiveness: hide the logo progressively — first when the viewport is too narrow, then a little before the rest of the header at short heights, where a vertical resize could otherwise leave a ghost of the inline image. - Add unit tests for the header's responsive thresholds. * Drop the unused HeaderHeight constant and dedupe the header config build Follow-up to review feedback on the shared-header redesign: - Remove the HeaderHeight constant. Nothing referenced it (callers compute height via HeaderHeightFor), and its doc described a "maximum" that HeaderHeightFor does not actually enforce, so the comment was misleading. - In the view and modify View() methods, build the header config once and reuse it for both RenderHeader and the height reservation instead of rebuilding it twice per frame. The click/scroll handlers keep deriving the height from the same config, so the header's dimensions remain a single source of truth.
Configuration menu - View commit details
-
Copy full SHA for 0efc764 - Browse repository at this point
Copy the full SHA 0efc764View commit details -
Add an interactive submit TUI for customizing each PR's title, descri…
…ption, and draft state (#147) * Add submitview data model and PR draft override plumbing Introduce the internal/tui/submitview package that will back the new interactive `gh stack submit` TUI, and wire its per-PR override contract into the submit command without changing current behavior. - submitview: BranchState model (NEW/OPEN/DRAFT/QUEUED/MERGED/CLOSED) with selectability/editability rules, SubmitNode UI state with edit detection, PRDraft override type, state derivation, title/description prefill, and state-badge/panel/tab styles. - submit: refactor ensurePR/createPR to accept an optional per-branch override map (title/body/draft/include); deselected NEW branches are pushed but get no PR. The override map is nil on the --auto / non-interactive path, so the agent-compat contract is unchanged. Fully unit tested. * Add single-screen submit TUI Introduce an interactive, single-screen editor for `gh stack submit`, built on Bubble Tea and Lip Gloss. The left panel renders the stack as a connected tree down to the trunk. Every branch without a PR is included by default; deselect one with its checkbox or `^x`. Because each PR builds on the branch below it, deselecting a branch also deselects the ones stacked above it, and re-including a branch re-includes the ones below it that it depends on. The cursor uses its own cyan accent so it reads distinctly from the green new/included color; existing PRs are shown dimmed with a no-entry glyph. The right panel edits the focused branch's PR in web-create-PR order: a header with the branch name and an include chip ("Creating PR" / "Skipped"), the title, a scrollable description (Glamour markdown preview and $EDITOR escape, with a scrollbar and mouse click-to-position), and a ready to draft segmented toggle (defaulting to ready). A footer strip shows the PR progress, the next branch, and the editor hints. Skipping a branch dims its body; branches that already have a PR show a read-only card linking to the PR. It shares the gh-stack header (art, title, stack info, and keyboard shortcuts) with `gh stack view` and `gh stack modify` for a unified look. Submit every included PR at once with Ctrl+S. Full keyboard and mouse support throughout. * Wire the single-screen submit TUI into `gh stack submit` Launch the submit editor from `gh stack submit` in interactive terminals, collecting per-branch PR drafts and applying them in a single batch. In non-interactive terminals or with --auto, fall back to auto-generated titles and skip the editor. Update the README and CLI reference to describe the single-screen flow. * Use the API PR title/body for existing PRs and fix new-PR defaults For existing PRs, the submit TUI showed a commit/template-derived draft instead of the pull request's real title and body. Fetch the actual title and body and render them in the read-only card: - open/draft/queued (tracked) and adopted-open PRs now carry title/body through the existing batch sync (added the fields to the GraphQL queries and PRDetails — no extra round trips), and - merged branches (which skip the live refresh) are filled in by a targeted enrichment step run only when the submit TUI opens. Also align the new-PR defaults with the non-TUI submit's defaultPRTitleBody: - Title: the commit subject only when the branch has exactly one commit, otherwise the humanized branch name (was: the oldest commit's subject even for multi-commit branches). - Description: the PR template, else the single commit's body, else empty (removed the bulleted commit-subject list for multi-commit branches). * Stop mouse wheel from leaking escape characters into form fields Scrolling the mouse wheel while a title or description field was focused could insert stray characters such as "[<65;54;51M" into the field. The submit TUI ran the Bubble Tea program with WithMouseAllMotion (mode 1003), which reports an event on every pointer move. During a wheel scroll that floods the input stream, and under that volume Bubble Tea splits an SGR mouse escape sequence ("\x1b[<Cb;Cx;Cy(M|m)") across input reads; the leftover bytes of a partially-parsed sequence are then emitted as key runes and inserted into the focused text input. Two changes fix this: - Switch to WithMouseCellMotion (mode 1002), which reports clicks, drag, and wheel but not idle pointer motion. That removes the per-move input flood, so under a real terminal's reads (up to 256 bytes) the only fragment that still surfaces is a single, clean burst at each wheel notch boundary. The TUI never used idle-hover for rendering, so cell-motion loses nothing. - Drop any leaked fragments before they reach a field. A split SGR mouse sequence surfaces as an Alt+"[" (the consumed "\x1b[") followed by body fragments ("<65;54;5", "1M"), or occasionally the whole body in one run ("[<65;54;51M"). consumeLeakedMouseKey recognises the start, swallows the body up to its "M"/"m" terminator, and bails out the moment a rune does not fit an SGR body, so ordinary typing (including "<", ";", digits, "M") and bracketed pastes are never eaten. Tests cover every split point of an SGR sequence, single-run tails, preserved real typing, a stray Alt+"[", bracketed paste, and that wheel events never modify the focused field. Verified end-to-end by feeding 1,500 wheel sequences through the real parser under terminal-sized reads and confirming the field stays empty. * Re-enable mouse tracking after the external editor closes Opening the description in $EDITOR with ^e and then quitting left the mouse unresponsive: clicks and wheel scrolling stopped working while keyboard navigation still did. The editor is launched with tea.ExecProcess, which releases the terminal before running the command and calls Bubble Tea's RestoreTerminal when it returns. RestoreTerminal re-enables the alt-screen, bracketed paste, and focus reporting, but it does not re-enable mouse tracking. The editor (e.g. vim) disables mouse reporting on exit, so once control returns to the TUI the terminal no longer emits mouse events. Re-arm mouse mode when the editor-finished message arrives by batching tea.EnableMouseCellMotion with the handler's command. That re-enables cell-motion and SGR mouse reporting, matching the WithMouseCellMotion option the program starts with, on every editor-return path (success or error). * dead code cleanup * support mouse input to move cursor in title field * use textArea for title to support word wrap for long inputs
Configuration menu - View commit details
-
Copy full SHA for b6bcce1 - Browse repository at this point
Copy the full SHA b6bcce1View commit details -
Adapt theme colors to light and dark terminals (#149)
* Make the TUIs adapt to light and dark terminal backgrounds The submit, view, and modify TUIs were tuned for dark terminals. On light or solarized-light backgrounds the result was hard to read and inverted: primary text used ANSI white (invisible on white), dim chrome used light grays (too faint), and accents used bright cyan (low contrast) — so "active" things looked lighter than "disabled" ones. Introduce a centralized, background-aware color palette and migrate all three TUIs to it: - internal/tui/shared/theme.go: a semantic palette of lipgloss.AdaptiveColor values (primary/muted/faint text, chrome/border, accent, PR-state colors, badge backgrounds, row shade, button, switch). lipgloss resolves the light/dark variant per render from the terminal background, which Bubble Tea detects at startup; terminals that don't report it fall back to dark, preserving the original look. - Replace every hardcoded ANSI color in shared/, submitview/, and modifyview/ with palette roles. The four pre-rendered status icons now render at use-time so their adaptive colors resolve correctly. The submit markdown preview picks glamour's light or dark style from the detected background. - GH_STACK_THEME=auto|light|dark forces the palette for terminals that mis-detect (some SSH/tmux setups); wired via the root command's PersistentPreRun before any render. Documented in the README and CLI docs. Neutral text/chrome use truecolor hex (GitHub Primer-inspired) for predictability across themes, including solarized which repurposes ANSI 8-15; lipgloss downsamples on terminals without truecolor. Tests verify the palette resolves differently for light vs dark and that GH_STACK_THEME is honored. * Apply background-aware colors to all command output Background detection and the GH_STACK_THEME override (added for the TUIs) only affected the interactive screens. Plain command output -- status messages and interactive prompts -- went through the mgutz/ansi library with fixed ANSI palette names (green/red/yellow/cyan/...), so it never adapted to the terminal background and could read poorly on light or solarized themes. Unify everything on the same adaptive palette so all colors react to the detected background and to GH_STACK_THEME. - Extract internal/theme, a foundational package with no internal dependencies, that owns: - the background-aware lipgloss.AdaptiveColor palette (moved out of internal/tui/shared), - ApplyOverride(), the GH_STACK_THEME=auto|light|dark logic, and - non-TUI colorizers (Success/Error/Warning/Blue/Magenta/Cyan/Gray/ Bold) plus FgSeqs(), which returns the raw start/reset escapes used to color the user's echoed prompt input. - internal/tui/shared/theme.go now re-exports the palette, so the TUI code keeps referring to shared.ColorX unchanged. - internal/config/config.go wires the Config.Color* funcs to the theme colorizers and drops mgutz/ansi (now an indirect dependency only). - cmd/utils.go colors the prompt icon and echoed input via theme. - cmd/root.go calls theme.ApplyOverride() in PersistentPreRun. Detection adds no cost: because the command package imports Bubble Tea, its init() already triggers (and caches) the terminal background query for every command, so the non-TUI colorizers just read the cached value. Terminals that don't answer the query fall back to the dark palette; GH_STACK_THEME=light|dark forces it. Colors are truecolor on capable terminals and downsample to the nearest ANSI color elsewhere. Tests: internal/theme covers palette adaptiveness, ApplyOverride, the colorizers, and FgSeqs; a new internal/config test verifies the wired-up Config.Color* funcs adapt to the background when color is enabled. Docs: README and the CLI reference note that GH_STACK_THEME now controls all colored output, not just the interactive screens. No behavior change beyond colors.Configuration menu - View commit details
-
Copy full SHA for 797c62e - Browse repository at this point
Copy the full SHA 797c62eView commit details -
Adopt an existing remote stack on submit instead of erroring (#153)
When a stack existed on GitHub but was not recorded in the local tracking file (`.git/gh-stack`, i.e. `s.ID == ""`) -- for example a stack created from the web UI or in another clone -- `gh stack submit` blindly called the create-stack API. The server rejected the request because the PRs were already stacked, surfacing a confusing, dead-end error: Could not create stack: Pull requests are already part of a stack. `syncStack()` only ever consulted the local `s.ID`. When it was empty it always POSTed to create, and the only handling for the rejection (`handleCreate422`) parsed the error string and at best printed "up to date" -- it never imported the remote stack ID, so the local/remote mismatch was never resolved and recurred on every submit. Detect and adopt the existing stack before creating one. When `s.ID` is empty and there are at least two PRs, `syncStack` now lists the repository's stacks and reconciles, mirroring the patterns already used by `checkout` and `link`: - No remote stack contains our PRs -> create a new one (unchanged). - The remote stack's PRs are all tracked locally (an exact match, or e.g. two of three already stacked with a third added on top) -> adopt the remote stack ID into local tracking and PUT the full, ordered PR list, appending any new PRs to the top. The adopted ID is persisted by the existing stack.Save in runSubmit. - The remote stack contains PRs we are not tracking locally -> refuse and warn rather than silently dropping them, pointing the user to `gh stack checkout <pr>` to import the full stack first. - Our PRs are spread across multiple remote stacks (an unresolvable divergence, since a PR can belong to only one stack) -> warn and skip. The new logic reuses `findMatchingStack`, `formatPRList`, and `slicesEqual` from the link command; `syncStack`'s signature is unchanged, and adoption is best-effort: listing failures degrade to the previous create path and never fail the submit, since the PRs are already pushed and created. Also broaden the create-stack 422 fallback (`handleCreate422`) to recognize the server's "already part of a stack" phrasing in addition to "already stacked", so that if the stack listing is unavailable the message is still actionable instead of the raw "Could not create stack" error above. Tests: six new cases in cmd/submit_test.go cover exact-match adoption (ID imported, no create/update call), additive two-of-three adoption (update with the full list), remote-superset refusal, PRs spanning multiple stacks, the ListStacks-error fallthrough to create, and the broadened fallback phrasing. Existing syncStack tests are unchanged.Configuration menu - View commit details
-
Copy full SHA for 9b30b7f - Browse repository at this point
Copy the full SHA 9b30b7fView commit details -
Fork unmerged branches into new stack (#154)
* Fork unmerged branches into a new stack when the base stack is fully merged Once every PR that is officially part of a stack on GitHub has been merged -- especially after the merged branches are deleted upstream -- you can no longer add to that stack. A new PR on top would target the trunk directly instead of chaining onto the merged PRs, so the remote stack's "each PR's base ref is the previous PR's head ref" invariant no longer holds. On the next `gh stack submit`, the stack update was rejected and surfaced as a confusing, dead-end warning: Failed to update stack on GitHub: Pull requests must form a stack, where each PR's base ref is the previous PR's head ref `submit` had no handling for this: `syncStack` always sent the full PR list (including the merged-and-deleted ones), so the API rejected the broken chain even though the new PRs had already been created with correct bases. Fork the survivors into a fresh stack instead of failing. After syncing PR state and before pushing, `runSubmit` now calls `maybeForkFromMergedBase`: - It triggers only when every PR officially part of the tracked remote stack (`s.ID`) has merged. Membership is read from the stacks API, so open PRs that are not part of the remote stack do not count, and -- this is the key guard -- a normal partial, bottom-up merge (where the remote stack still lists an open PR) is left completely untouched. A cheap pre-check (the local stack must have at least one merged branch) avoids an extra ListStacks call on the common path. - The local branches are partitioned: those still in the merged remote stack stay behind; everything else (new branches, plus open PRs that were never part of that remote stack) is lifted into a brand-new stack rooted at the original trunk, with an empty remote ID. The bottom survivor is re-based onto the trunk. - `runSubmit` continues with the new stack, so the push loop, PR creation, and `syncStack` all operate on it; the empty ID routes `syncStack` through the adopt/create path and a fresh stack is created on GitHub. - The original, fully merged stack is left untouched on GitHub. Locally it is kept as a record only if at least one of its branches still exists in the working copy; otherwise it is dropped. No data is lost -- those PRs are already merged on GitHub. To restructure the stack file safely, add `StackFile.IndexOfStack`, which locates a stack by pointer identity so the fork can capture what it needs before `AddStack`/`RemoveStack` reallocate the underlying slice. Also soften the partial-merge case that does not fork: when an `UpdateStack` call fails with the "must form a stack" 422 and the stack still contains merged branches, report it as an informational note (the unmerged PRs were pushed and re-based onto the trunk) rather than a scary failure warning. Scope is limited to `submit`. `add` and `checkout` keep their existing "refuse and suggest `gh stack init`" behavior on fully merged stacks. Tests: - cmd/submit_test.go: TestSubmit_ForksWhenRemoteStackFullyMerged covers both disposition variants (the old stack is removed when its merged branches are gone locally, kept when they still exist) and asserts that only the new branches are pushed, the fork message is printed, a fresh stack is created, and the local stack file is split into two stacks. TestSubmit_NoForkWhenRemoteStackHasOpenPR verifies the everyday bottom-up merge is not forked and that the broken-chain 422 is reported calmly. TestUpdateStack_BrokenChainAfterMerge checks the calm-vs-warn branch. - internal/stack/stack_test.go: TestIndexOfStack covers identity lookup and the not-found case. Docs: README, the CLI reference, the stacked-PRs guide, the FAQ, and the agent SKILL.md note that submitting onto a fully merged stack starts a new stack rooted at the trunk. * Handle fully merged stacks gracefully in the view and modify TUIs Merged branches (and their PRs) are not selectable, so once an entire stack has landed there is nothing to act on -- yet the TUIs did not reflect that: - `gh stack view` still drew a highlighted cursor on the top branch even though it could not be selected. Navigation, checkout, and the per-branch toggles all silently did nothing, with no indication of why. - `gh stack modify` opened its full editor on a stack with nothing left to restructure, instead of short-circuiting like `gh stack submit` does when there is nothing to submit. Reflect the "nothing actionable" state in both TUIs. View (internal/tui/stackview/model.go): - Hide the cursor when every branch is merged. `New` now starts the cursor at -1 and only lands it on the current or first non-merged branch; when none exists the cursor stays hidden, so no row is rendered as focused. The existing `m.cursor >= 0` guards and merged-skipping `moveCursor` already make every cursor action a no-op in that state, and mouse-wheel scrolling still works for tall merged stacks. - Dim the shortcuts that depend on the cursor. `buildHeaderConfig` marks navigate, commits, files, open PR, and checkout as `Disabled` (rendered gray via the existing ShortcutEntry.Disabled styling) when all branches are merged, leaving only `q quit` active. Modify (cmd/modify.go): - Short-circuit before opening the TUI. After preconditions pass and PR state is synced, `runModify` now returns early when the stack is fully merged, printing "All branches in this stack have been merged" and pointing at `gh stack init`, exiting cleanly (exit 0) like submit's "nothing to submit" path. The linearity and merge-queue precondition checks already skip merged branches, so they do not fire spuriously. Tests: - internal/tui/stackview/model_test.go: the cursor is hidden (-1) when all branches are merged; up/down/enter do not move it or trigger a checkout; View renders without panicking on a hidden cursor; buildHeaderConfig disables every cursor-dependent shortcut (and only those) when all merged, and leaves them all enabled when active branches remain. - cmd/modify_test.go: runModify short-circuits on a fully merged stack, printing the message and returning no error without launching the TUI.Configuration menu - View commit details
-
Copy full SHA for 754d190 - Browse repository at this point
Copy the full SHA 754d190View commit details -
Create/update stack on remote during sync (#156)
* Create/update the remote stack on sync and fix false "Stack synced" `gh stack sync` reported "Stack synced" even when it had not created or updated the stack object on GitHub. After running `gh stack init` to adopt existing branches and then opening PRs outside the CLI, `gh stack sync` detected the open PRs and printed "Stack synced" — but no stack had ever been created on the server. There were two distinct bugs: 1. Sync never reconciled the remote stack object. `runSync` called `syncStackPRs`, which only *reads* PR state and links PRs to local branches; it never called the create/update path. So the branches were rebased and pushed and the PRs were detected, but the stack on GitHub was never created. 2. The final message was unconditional. `runSync` always printed "Stack synced", which is supposed to mean "the stack object on GitHub now reflects the local stack" — something that can only be true when two or more open PRs exist and the remote stack was actually created/updated. Fix Reconcile the remote stack from sync, and make the closing message reflect what actually happened. * cmd/sync.go - Add a reconciliation step (5b) after PR-state sync: when the stack has two or more open PRs, link them into a stack on GitHub via the new `syncRemoteStack` helper. It inspects existing stacks first and: - short-circuits quietly when a remote stack already lists exactly these PRs (records the ID, prints "Stack already up to date on GitHub") so routine syncs don't issue a redundant, misleading update; - otherwise delegates to `syncStack` to create a new stack, adopt an untracked one, or update a partially-formed one. Sync never opens PRs — that remains `gh stack submit`'s job. - Replace the unconditional "Stack synced" with a result-driven message: "Stack synced" when the remote stack object was created/updated/in sync, otherwise "Branches synced" (fewer than two PRs, stacked PRs unavailable, a cross-stack divergence, or no GitHub client). - Update the command's long description to document the stack-object step and the two possible closing messages. * cmd/submit.go - Thread a `synced bool` return through the existing, tested stack helpers so sync can tell whether the remote stack object now matches local: `syncStack`, `createNewStack`, and `updateStack` now return `bool`; `adoptRemoteStack` returns `(handled, synced)`; and `handleCreate422` returns `bool` (true only when the PRs are already stacked together). Extract the shared `stackPRNumbers` helper. - This is additive: submit's single call site ignores the new return value, so submit's behavior, output, and tests are unchanged. Reusing these helpers (instead of duplicating the 404/422 handling in sync) keeps the create/adopt/update logic in one tested place. Tests * cmd/sync_test.go — six new cases covering the reconciliation matrix: - TestSync_CreatesRemoteStackWhenPRsExist: open PRs but no remote stack -> CreateStack is called and the new ID is persisted to the stack file; output contains "Stack created on GitHub" and "Stack synced". - TestSync_AdoptsExistingEqualRemoteStack: a matching remote stack -> no create/update, ID recorded, "Stack synced". - TestSync_UpdatesPartialRemoteStack: a subset stack -> UpdateStack with the full PR list, "Stack synced". - TestSync_FewerThanTwoPRs_BranchesSynced: one PR -> no stack API calls, "Branches synced", not "Stack synced". - TestSync_StacksUnavailable_BranchesSynced: 404 on create -> warns, "Branches synced". - TestSync_PRsSpanMultipleStacks_BranchesSynced: PRs across two stacks -> divergence warning, no create/update, "Branches synced". Docs Document the new stack-object step and the "Stack synced" vs "Branches synced" distinction in: - README.md - docs/src/content/docs/reference/cli.md - skills/gh-stack/SKILL.md - docs/src/content/docs/introduction/overview.md - docs/src/content/docs/guides/stacked-prs.md - docs/src/content/docs/guides/workflows.md * Address PR review: one ListStacks per sync, command-neutral guidance Two follow-ups from the #156 review (both flagged optional / non-blocking). 1. Remove the redundant ListStacks round-trip on sync's create path. syncRemoteStack fetched the stack list for its already-up-to-date short-circuit, then delegated to syncStack -> adoptRemoteStack, which listed the stacks again — two GETs on the first-sync-create and membership-changed paths. Refactor adoptRemoteStack into a list-accepting reconcileUntrackedStack(cfg, client, s, prNumbers, stacks): syncStack now fetches the list once and passes it down, and syncRemoteStack reuses the list it already fetched. Net: exactly one ListStacks per sync. This also drops the (handled, synced) tuple. Submit's behavior is unchanged. 2. Make the divergence / dropped-PR guidance command-neutral. The shared helper emitted submit-specific wording ("reconcile them before submitting", "...then `gh stack submit`") that is now reachable from `gh stack sync`. Reword to "reconcile them first" and drop the trailing `gh stack submit` so it reads correctly from either command. Tests: assert exactly one ListStacks on the create path and that the divergence guidance is not submit-specific. * increment skill file version * Simplify sync reconciliation: reuse syncStack instead of a parallel path Review feedback noted the change felt heavier than the fix warranted. The weight came from `syncRemoteStack` (cmd/sync.go), a near-duplicate of submit's `syncStack` — same <2-PR guard, ListStacks, and update/create dispatch — that existed only to add an "already up to date" short-circuit. That one optimization is what spawned the second entry point, the pre-fetched-list threading, and the double-ListStacks it then required. Collapse it to a single reconciliation path: - Remove `syncRemoteStack`; `gh stack sync` now calls the shared `syncStack` directly. One path, one ListStacks per sync. - Fold `createNewStack` into `reconcileUntrackedStack` (renamed from `adoptRemoteStack`) so it returns a single `synced bool` instead of a `(handled, synced)` tuple and owns its own ListStacks again. - Inline `stackPRNumbers` back into `syncStack` (it was only extracted to share with the now-removed `syncRemoteStack`). - Drop the now-unused `strconv`/`github` imports from cmd/sync.go. Behavior note: a routine re-sync of an already-tracked stack now prints "Stack updated on GitHub with N PRs" instead of "Stack already up to date on GitHub". This is accurate (sync does PUT the current state) and matches submit. The "Stack synced" / "Branches synced" summary is unchanged, and submit's behavior is unchanged.Configuration menu - View commit details
-
Copy full SHA for e208dfc - Browse repository at this point
Copy the full SHA e208dfcView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v0.0.6...v0.0.7