Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: github/gh-stack
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.0.7
Choose a base ref
...
head repository: github/gh-stack
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.0.8
Choose a head ref
  • 14 commits
  • 71 files changed
  • 2 contributors

Commits on Jun 30, 2026

  1. Bump astro in /docs in the npm_and_yarn group across 1 directory (#138)

    Bumps the npm_and_yarn group with 1 update in the /docs directory: [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro).
    
    
    Updates `astro` from 6.3.1 to 6.4.8
    - [Release notes](https://github.com/withastro/astro/releases)
    - [Changelog](https://github.com/withastro/astro/blob/astro@6.4.8/packages/astro/CHANGELOG.md)
    - [Commits](https://github.com/withastro/astro/commits/astro@6.4.8/packages/astro)
    
    ---
    updated-dependencies:
    - dependency-name: astro
      dependency-version: 6.4.8
      dependency-type: direct:production
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Jun 30, 2026
    Configuration menu
    Copy the full SHA
    97c1b31 View commit details
    Browse the repository at this point in the history
  2. Bump the npm_and_yarn group across 1 directory with 2 updates (#159)

    Bumps the npm_and_yarn group with 1 update in the /docs directory: [esbuild](https://github.com/evanw/esbuild).
    
    
    Updates `esbuild` from 0.27.4 to 0.28.1
    - [Release notes](https://github.com/evanw/esbuild/releases)
    - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
    - [Commits](evanw/esbuild@v0.27.4...v0.28.1)
    
    Updates `vite` from 7.3.2 to 8.1.0
    - [Release notes](https://github.com/vitejs/vite/releases)
    - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
    - [Commits](https://github.com/vitejs/vite/commits/create-vite@8.1.0/packages/vite)
    
    ---
    updated-dependencies:
    - dependency-name: esbuild
      dependency-version: 0.28.1
      dependency-type: indirect
      dependency-group: npm_and_yarn
    - dependency-name: vite
      dependency-version: 8.1.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>
    dependabot[bot] authored Jun 30, 2026
    Configuration menu
    Copy the full SHA
    514f5ab View commit details
    Browse the repository at this point in the history

Commits on Jul 15, 2026

  1. Ignore symlinked pull request templates (#164)

    Template discovery in internal/pr read candidate template paths with
    os.ReadFile, which follows symlinks. A pull request template that is a
    symlink (for example .github/pull_request_template.md pointing to a file
    outside the repository) would therefore be read through to its target, and
    that target's contents would be used as the PR body by `gh stack submit`
    and `gh stack link`.
    
    Reuse cli/cli's githubtemplate package (already a dependency) for template
    discovery instead of the hand-rolled path list. It is the same code
    `gh pr create` uses, and it ignores symlinked templates, so only regular
    template files inside the repository are read. FindTemplate keeps the same
    signature, so the submit and link callers are unchanged.
    
    Two behavior changes come with the switch:
    - YAML front-matter is stripped from the template, matching `gh pr create`.
    - Template filename matching is slightly broader; hyphenated and non-.md
      variants are now recognized.
    
    Add tests for FindTemplate and for the `gh stack submit --auto` and
    `gh stack link` PR-creation flows to confirm symlinked templates are not
    followed.
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    5975945 View commit details
    Browse the repository at this point in the history
  2. Fully-qualify branch refspecs when pushing (#165)

    * Fully-qualify branch refspecs when pushing
    
    gh-stack builds `git push` arguments from stack branch names in `internal/git`.
    The force path passed `<branch>:refs/heads/<branch>`, and the non-force path
    passed bare branch names. A git refspec treats a leading `+` as "force update",
    and Git allows branch names that begin with `+`, so a branch named `+feature`
    was parsed as refspec syntax for `feature`: the force path pushed local
    `feature` into remote `+feature`, and the non-force path force-updated remote
    `feature`.
    
    Build fully-qualified refspecs for both the source and destination of every
    push: `refs/heads/<branch>:refs/heads/<branch>`. A branch name can no longer be
    reinterpreted as a refspec modifier. Force updates are still requested via the
    existing `--force-with-lease` flags, whose ref names were already
    fully-qualified. `DeleteRemoteBranch` is fully-qualified the same way.
    
    The `Push` signature and every call site are unchanged. Add real-git
    integration tests covering the force and non-force paths with a `+`-prefixed
    branch.
    
    * rm redundant if and simplify
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    ae5f889 View commit details
    Browse the repository at this point in the history
  3. Fix to properly revert after aborting modify (#167)

    * Add cherry-pick abort/quit/in-progress git primitives
    
    Introduce IsCherryPickInProgress() (detects .git/CHERRY_PICK_HEAD) and split
    the existing cherry-pick reset into two distinct operations:
    
    - CherryPickQuit() runs `git cherry-pick --quit`, clearing the sequencer
      state without touching the index (used to clear stale state before starting
      a fresh cherry-pick).
    - CherryPickAbort() now runs `git cherry-pick --abort`, which fully restores
      the working tree and index to the pre-cherry-pick state.
    
    The previous CherryPickAbort() ran --quit, which leaves an unmerged index and
    therefore cannot recover a conflicted fold-down. Integration tests cover the
    in-progress detection, the full abort restore, and the --quit-leaves-index
    behavior.
    
    * Fix modify --abort leaving a broken stack after a conflict
    
    When `gh stack modify` hit a rebase or cherry-pick conflict it saved state
    with phase "conflict" and told the user to run `gh stack modify --abort` to
    restore. But runModifyAbort had no case for PhaseConflict, so it fell into the
    default branch that merely printed "unexpected modify state phase" and deleted
    the state file without unwinding. The in-flight rebase/cherry-pick stayed
    active, branches were left partially rewritten, and the deleted state file also
    made --continue impossible: the stack was stuck in limbo.
    
    Fixes:
    
    - runModifyAbort now unwinds on PhaseConflict (same recovery as PhaseApplying),
      aborting the in-progress operation, resetting branch tips to their pre-modify
      SHAs, restoring stack metadata, and clearing state.
    - Unwind now also aborts an in-progress cherry-pick (fold-down conflicts), not
      just a rebase. Without this the restore checkouts would fail on the unmerged
      cherry-pick index.
    - ContinueApply now records a subsequent cascade-rebase conflict as
      ConflictType "rebase" instead of leaving a stale "cherry_pick", so the next
      --continue calls RebaseContinue rather than failing in CherryPickContinue.
    
    Adds coverage for the conflict-phase abort, pending-submit no-op abort, Unwind
    aborting an active cherry-pick, and the cherry-pick to rebase ConflictType
    transition.
    
    * Persist fold-branch removal when a post-fold cascade rebase conflicts
    
    ContinueApply removes the folded branch from the in-memory stack after a
    fold-down cherry-pick is resolved, but a subsequent cascade rebase conflict
    only saved the modify state file, not the stack metadata. On the next
    --continue the on-disk metadata (folded branch still present) was re-read, and
    because ConflictType is now "rebase" the fold-removal block was skipped, so the
    final save resurrected the folded branch as a phantom entry pointing at an
    orphaned tip.
    
    Persist the stack file alongside the state file on a cascade-rebase conflict,
    mirroring ApplyPlan's save-on-conflict, so the fold removal survives recovery.
    Adds an end-to-end regression test covering the fold-then-cascade-conflict path
    across two --continue calls.
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    0c51c08 View commit details
    Browse the repository at this point in the history
  4. Fix link failing when an existing stack PR is queued for merge (#171)

    gh stack link validated PR eligibility before it fetched the repository's
    stacks, so validatePREligibility rejected any queued PR unconditionally —
    including one already a member of the stack being updated. Because link is
    additive (every existing stack PR must be re-listed or the update is refused
    for dropping them), a stack whose bottom PR was in the merge queue could never
    take new PRs on top: re-listing the queued PR failed eligibility, and omitting
    it failed the drop check.
    
    Fetch the stacks and resolve the target stack before validating eligibility,
    then skip the eligibility checks (queued, auto-merge, merged, closed) for any
    PR that is already a member of that stack — those PRs are not being added, so
    the checks don't apply. PRs not already in the stack, and brand-new stacks,
    keep the previous strict behavior. prevalidateStack now takes the resolved
    stack instead of looking it up a second time.
    
    Add coverage for linking new PRs onto a stack whose existing PR is queued,
    merged, or has auto-merge enabled, and for still rejecting a queued PR that is
    not yet part of the target stack.
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    46b5dc4 View commit details
    Browse the repository at this point in the history
  5. Fix rebase treating queued PRs as merged (#173)

    * Don't treat queued PRs as merged when rebasing the stack
    
    gh stack rebase and gh stack sync share cascadeRebase, which skipped
    branches via IsSkipped() (merged or queued) and then switched to a
    `git rebase --onto` that drops the skipped branch's commits from every
    downstream branch. That is right for a merged PR — its commits are
    already in trunk — but wrong for a queued PR: its commits only exist on
    its own branch, which is frozen in the merge queue, so the branches
    above it were rebased onto trunk and lost work they depend on.
    
    Handle the two cases separately. A merged branch still activates --onto
    so its commits are dropped. A queued branch is still skipped (its branch
    is frozen and is not rebased or pushed), but onto mode is reset so
    downstream branches rebase normally onto the queued branch, keeping its
    commits underneath. The --onto target search, the runRebase --onto seed,
    and the continueRebase display base now key on IsMerged() instead of
    IsSkipped(), so a queued predecessor no longer forces downstream
    branches onto trunk. gh stack sync is fixed through the same shared
    helper.
    
    Add rebase coverage for a queued branch mid-stack, a merged branch below
    a queued branch, and --upstack above a queued branch, plus a sync test
    that also asserts the queued branch is excluded from the push. The
    transient queued state is injected through the GitHub mock's merge-queue
    entry.
    
    * Refresh queued PR state when continuing a stack rebase
    
    continueRebase reloads the stack from disk, where the Queued flag is
    transient (json:"-") and therefore lost, and it only called syncStackPRs
    after the cascade. So if the initial rebase conflicted on a branch below
    a queued branch, `gh stack rebase --continue` resumed with that branch
    seen as active: it rebased the frozen merge-queue branch and rebuilt the
    downstream branches on a local history that differs from the queued
    branch.
    
    Call syncStackPRs right after resolving the stack — before selecting the
    base and cascading the remaining branches — mirroring the refresh
    runRebase already does before its cascade. The queued flag is
    repopulated, so queued branches stay skipped and downstream branches
    stay stacked on them.
    
    Add TestRebase_Continue_QueuedBranchBelowConflict, which conflicts below
    a queued branch and asserts the frozen branch is not rebased and the
    branch above stays stacked on it. Verified to fail without the refresh.
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    623b7e6 View commit details
    Browse the repository at this point in the history
  6. Sync remote stack with local stack state (#175)

    * pull in remote updates during sync
    
    * cancel aborts operation
    
    * switch to nearest surviving branch
    
    * simplified options to remote delete
    
    * stack existing PRs from submit TUI
    
    * docs updates
    
    * address review comments
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    95f04b8 View commit details
    Browse the repository at this point in the history
  7. Migrate to new Stacks REST API (#177)

    * Add stack Number field to local model and schema
    
    The new Stacks REST API exposes a human-facing stack number (shown in the
    github.com UI) alongside the internal stack id. Add a Number field to the
    stack.Stack model and document it in schema.json so it can be persisted in
    the .git/gh-stack file. Purely additive; behavior is unchanged until callers
    populate it.
    
    Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
    
    * Cut over stack operations to the public Stacks REST API
    
    Replace the private cli_internal stack endpoints with the new public
    Stacks REST API (/repos/{owner}/{repo}/stacks):
    - ListStacks / FindStackForPR (?pull_request= filter) / GetStack for reads
    - CreateStack, which now returns the created stack including its number
    - AddToStack for delta-only appends (there is no full-replace endpoint)
    - Unstack for server-driven removal (204 dissolved / 200 partial / 422)
    
    Migrate all callers (checkout, submit, link, sync, unstack, utils) and
    drop the client-side unstack eligibility pre-check — the server now
    decides which PRs can be unstacked. checkout discovers stacks via the
    pull_request filter; submit/link express updates as append-only deltas;
    unstack adopts partial-unstack semantics, keeping local tracking when
    PRs remain stacked on GitHub.
    
    RemoteStack now carries the stack number, and stack updates resolve a
    stack's number from its internal id for stack files that predate the
    Number field.
    
    Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
    
    * Remove the personal access token (PAT) limitation
    
    The new Stacks REST API is public, so any user authenticated with the
    GitHub CLI (including via a PAT with repo scope) can perform stack
    operations once the feature is enabled for their repository. Remove the
    PAT detection and the private-preview gating:
    
    - Delete Config.WarnIfPAT / IsPersonalAccessToken and the TokenForHostFn
      test hook (internal/config/auth.go is no longer needed).
    - Drop the submit pre-flight that aborted on a PAT.
    - Rename warnStacksUnavailableOrPAT to warnStacksUnavailable and simplify
      it to the "stacked PRs not enabled" message.
    
    Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
    
    * address review comments
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    a82dc3e View commit details
    Browse the repository at this point in the history
  8. Stack number as primary identifier (#178)

    * Support addressing a stack by its stack number
    
    checkout now interprets a bare integer as a stack number first (the
    identifier shown in the github.com stack UI), falling back to a locally
    tracked PR number, then a PR number discovered from GitHub, then a branch
    name. A new checkoutStackByNumber resolves the stack via GetStack and
    checks out its top-most unmerged branch; the reconcile/import logic is
    shared with the PR-number path.
    
    unstack gains an optional <stack-number> positional argument to unstack a
    specific locally tracked stack instead of the current one.
    
    Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
    
    * Surface the stack number in output and TUIs
    
    Show the human-facing stack number wherever it is known:
    - Append a "(stack #N)" label to submit, link, checkout, and unstack
      success messages.
    - Add a "Stack #N" header line to the view command (short and static)
      and the stackview TUI header.
    - Add a "Stack #N" info line to the submit TUI header when submitting
      an already-created stack.
    
    Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
    
    * Update docs and agent instructions for the new API
    
    - cli.md: document checkout/unstack by stack number and drop the
      "PATs are not supported" note (any gh-authenticated user can now run
      stack operations).
    - quick-start.md: drop the PAT-not-supported note.
    - AGENTS.md / copilot-instructions.md: ClientOps is now 13 methods over
      the public Stacks REST API; remove the TokenForHostFn test hook; note
      the stack file's id/number identity.
    - SKILL.md: add checkout/unstack-by-stack-number quick references.
    
    Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
    
    * address review comments
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    f880f0d View commit details
    Browse the repository at this point in the history
  9. Interactive stack picker for checkout (#179)

    * Add an interactive stack picker for checkout
    
    Running `gh stack checkout` with no argument previously showed a plain
    text prompt of locally tracked stacks only. It could not surface stacks
    that exist only on the remote, gave no sense of a stack's state, and
    listed fully merged stacks that can no longer be added to.
    
    Replace it with an interactive picker (new package
    internal/tui/checkoutview) that lists every stack available to you,
    reconciling the local stack file with the Stacks REST API:
    
    - Merges local and remote stacks, matched by stack id/number, and labels
      each Local (present locally, even if also tracked on the remote) or
      Remote (only on GitHub). Fully merged stacks are filtered out.
    - Shows compact columns: stack number, first...last branch, base branch,
      a muted status bar summarizing merged/open/closed/unpushed PRs, type,
      and relative created time.
    - Offers All / Local / Remote tabs and `/` type-to-filter search.
    
    The picker renders inline rather than taking over the screen: it shows
    up to ten rows with a scroll indicator, shrinks to fit short terminals,
    and clears itself on exit.
    
    Selecting a locally available stack checks out its top unmerged branch;
    selecting a remote-only stack clones it down through the existing
    checkout-by-number import flow.
    
    When the Stacks API is unavailable (stacks not enabled, no auth, or a
    network error), the picker degrades gracefully to a local-only list.
    
    Also update the README, overview, and CLI reference for the new behavior.
    
    * search by entire branch list
    
    * address review comments
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    ceffffc View commit details
    Browse the repository at this point in the history
  10. Remote unstack by stack number (#180)

    * unstack as a pure api wrapper if stack not checked out locally
    
    * update unstack docs
    
    * address review comments
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    e0b2104 View commit details
    Browse the repository at this point in the history
  11. Append to an existing stack by stack number with link (#181)

    * link append to stack by number
    
    * updated link docs
    
    * address review comment
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    9dfef64 View commit details
    Browse the repository at this point in the history
  12. Deprecate branch name prefixes (#182)

    * deprecate prefix functionality
    
    * clean up branch auto-naming
    
    * update docs
    
    * preserve literal hyphens when slugifying branch names
    skarim authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    38aba1b View commit details
    Browse the repository at this point in the history
Loading