-
Notifications
You must be signed in to change notification settings - Fork 57
Comparing changes
Open a pull request
base repository: github/gh-stack
base: v0.0.5
head repository: github/gh-stack
compare: v0.0.6
- 11 commits
- 36 files changed
- 4 contributors
Commits on May 29, 2026
-
Bump github.com/cli/cli/v2 in the go_modules group across 1 directory (…
…#110) Bumps the go_modules group with 1 update in the / directory: [github.com/cli/cli/v2](https://github.com/cli/cli). Updates `github.com/cli/cli/v2` from 2.92.0 to 2.93.0 - [Release notes](https://github.com/cli/cli/releases) - [Changelog](https://github.com/cli/cli/blob/trunk/docs/release-process-deep-dive.md) - [Commits](cli/cli@v2.92.0...v2.93.0) --- updated-dependencies: - dependency-name: github.com/cli/cli/v2 dependency-version: 2.93.0 dependency-type: direct:production dependency-group: go_modules ... 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 5ed5693 - Browse repository at this point
Copy the full SHA 5ed5693View commit details
Commits on Jun 1, 2026
-
link: block merged, closed, queued, and auto-merge-enabled PRs (#112)
The `link` command previously allowed PRs in any state to be added to a stack, including PRs that had already been merged, were closed, were sitting in a merge queue, or had auto-merge enabled. Adding such PRs to a stack is invalid because they have already been or will soon be merged, which breaks the stacked PR workflow. Add a new validation phase (Phase 2b) to `runLink` that checks the eligibility of every existing PR found during lookup, before any new PRs are created or stack operations are performed. Only open/draft PRs without auto-merge enabled are eligible. All ineligible PRs are reported at once with a clear per-PR error message indicating the specific reason (merged, closed, in merge queue, or auto-merge enabled). Changes: internal/github/github.go: - Add AutoMergeRequest struct and field on PullRequest - Add IsAutoMergeEnabled() method on *PullRequest - Update FindPRByNumber and FindPRForBranch GraphQL queries to fetch the autoMergeRequest field internal/github/github_test.go: - Add TestPullRequest_IsAutoMergeEnabled (nil, non-nil, nil receiver) cmd/link.go: - Add pr field to resolvedArg to retain full PR data from lookup - Add validatePREligibility() that rejects merged/closed/queued/ auto-merge-enabled PRs with descriptive error messages - Wire validation into runLink between PR lookup and stack operations cmd/link_test.go: - Add 7 tests covering each disallowed state by PR number and branch name, plus a multi-invalid-PR reporting testConfiguration menu - View commit details
-
Copy full SHA for d2a390f - Browse repository at this point
Copy the full SHA d2a390fView commit details
Commits on Jun 15, 2026
-
alert for unsupported auth tokens (#113)
When users authenticate the GitHub CLI with a personal access token (PAT) instead of OAuth (`gh auth login`), the `cli_internal` stacks API endpoints return 404. The CLI previously interpreted this as "Stacked PRs are not enabled for this repository," which is misleading — the feature may be enabled, but the token type simply cannot access the internal endpoints. This is a recurring source of user confusion. The docs already note that PATs are not supported, but users don't always read them before hitting the error. This change adds token-type detection by inspecting the `gh` auth token prefix: - `gho_` → OAuth (supported) - `ghs_` → GitHub App installation token (supported) - `ghp_` → Classic PAT (NOT supported) - `github_pat_` → Fine-grained PAT (NOT supported) When a PAT is detected, the CLI now shows: ⚠ Personal access tokens are not supported by gh stack Run `gh auth login` to authenticate with OAuth instead. Instead of the misleading: ⚠ Stacked PRs are not enabled for this repository Changes: - Add `internal/config/auth.go` with auth detection methods on Config: `IsPersonalAccessToken()`, `WarnIfPAT()`, and `RepoHost()`. Uses a `TokenForHostFn` field on Config for test overrides, following the same pattern as `GitHubClientOverride`. - Add a pre-flight PAT check in `cmd/submit.go` before the `ListStacks` call. If a PAT is detected, the command aborts early with a clear error instead of making a doomed API call. - Update all 404 handlers for `cli_internal` endpoints to check the token type and show the appropriate message: - `cmd/submit.go` (createNewStack) - `cmd/link.go` (listStacksSafe, createLink) - `cmd/checkout.go` (checkoutRemoteStack) - Add `warnStacksUnavailableOrPAT()` helper in `cmd/utils.go` that shows the PAT-specific warning when applicable, falling back to the generic "not enabled" message for non-PAT tokens. - Add unit tests in `internal/config/auth_test.go` for token prefix detection and warning output. - Add integration tests in `cmd/submit_test.go` verifying that both classic PATs (`ghp_`) and fine-grained PATs (`github_pat_`) trigger the pre-flight check and abort before any API calls. - Add `warnStacksUnavailableOrPAT` tests in `cmd/utils_test.go` verifying correct message selection based on token type. - Update existing 404 tests to explicitly set an OAuth token so they continue exercising the ListStacks 404 path.Configuration menu - View commit details
-
Copy full SHA for d235a21 - Browse repository at this point
Copy the full SHA d235a21View commit details -
submit: disable auto-merge on existing PRs before adding to stack (#120)
When a user runs `gh stack submit` and an existing PR is discovered for a branch via `FindPRForBranch`, that PR may have auto-merge enabled. Auto-merge is incompatible with stacked PRs because the PR would merge on its own, breaking the stack's base chain. Previously, the eligibility guard for auto-merge was only in the `link` command (which blocks such PRs with an error). The `submit` command had no such check, allowing users to add auto-merge-enabled PRs to a stack by running `init` followed by `submit`. This change adds auto-merge detection and automatic disabling in `submit`'s `ensurePR` function. When an existing PR with auto-merge enabled is discovered, the CLI disables auto-merge via the `disablePullRequestAutoMerge` GraphQL mutation and warns the user. If the disable call fails, submit continues with a warning (non-fatal). The `link` command retains its stricter behavior of blocking auto-merge PRs outright, since the user explicitly chose those PRs and can fix them before retrying. Changes: internal/github/github.go: - Add DisableAutoMerge() method using the disablePullRequestAutoMerge GraphQL mutation internal/github/client_interface.go: - Add DisableAutoMerge(prID string) error to ClientOps interface internal/github/mock_client.go: - Add DisableAutoMergeFn field and mock implementation cmd/submit.go: - In ensurePR, after discovering an existing PR with auto-merge enabled, call DisableAutoMerge before proceeding. Warns on success ("Disabled auto-merge for PR #N (incompatible with stacked PRs)") and on failure ("failed to disable auto-merge"). cmd/submit_test.go: - Add TestSubmit_DisablesAutoMergeOnExistingPR: verifies auto-merge is disabled and warning is shown - Add TestSubmit_DisableAutoMergeFailure_ContinuesWithWarning: verifies submit continues even if the disable call fails - Add TestSubmit_NoAutoMerge_SkipsDisable: verifies DisableAutoMerge is not called for PRs without auto-mergeConfiguration menu - View commit details
-
Copy full SHA for a4485f5 - Browse repository at this point
Copy the full SHA a4485f5View commit details -
* Accept PR URLs in link and checkout commands Add support for GitHub PR URLs (e.g. https://github.com/owner/repo/pull/42) as arguments to `gh stack link` and `gh stack checkout`, in addition to the existing PR number and branch name support. For `link`: PR URLs are parsed in findExistingPR before the numeric check. Unlike numeric args, if a URL-extracted PR number doesn't exist, the command errors immediately rather than falling through to branch name lookup (since a URL can never be a valid branch name). For `checkout`: PR URLs are parsed in runCheckout before the numeric check, routing to resolveNumericTarget which supports both local and remote API fallback — same behavior as passing a PR number directly. Closes #115 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update docs --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 4999852 - Browse repository at this point
Copy the full SHA 4999852View commit details -
Fix force-with-lease push for branches without tracking refs (#124)
gh stack sync could rebase a stack successfully then fail the final force push with "stale info" when a branch lacked a local tracking ref (refs/remotes/<remote>/<branch>). This happened because: 1. FetchBranches pre-filtered branches by existing tracking ref, so a branch with no tracking ref was never fetched and never gained one. 2. Push used a bare --force-with-lease flag, which has no lease basis for a branch without a tracking ref, causing git to reject the push. FetchBranches now uses explicit refspecs for every branch: +refs/heads/<branch>:refs/remotes/<remote>/<branch> This creates or updates tracking refs regardless of prior state. The fast-path (single fetch) and per-branch fallback (for branches absent on the remote) are preserved. Push now builds explicit per-branch lease arguments when force=true: --force-with-lease=refs/heads/<branch>:<tracking-ref-sha> for branches with a tracking ref, or: --force-with-lease=refs/heads/<branch>: (empty expected value = "must not exist") for branches absent on the remote. Explicit destination refspecs (<branch>:refs/heads/<branch>) remove dependence on push.default and upstream configuration. The non-force push path is unchanged. Added 6 integration tests using real bare git remotes: - Branch with current tracking ref: push succeeds - Tracking ref deleted locally (regression test for #118): push succeeds - Remote advanced by another client: push rejected (safety preserved) - New branch absent on remote: created via empty-expect lease - New branch race condition: rejected (safety preserved) - Mixed stack (tracked + untracked branches): all succeed after fetch Fixes #118
Configuration menu - View commit details
-
Copy full SHA for 7413e88 - Browse repository at this point
Copy the full SHA 7413e88View commit details -
sync: skip trunk fast-forward silently when local branch doesn't exist (
#125) When the trunk branch (e.g. main) doesn't exist locally — only the remote tracking ref (origin/main) exists — `fastForwardTrunk` called `git rev-parse main origin/main` which failed, emitting: ⚠ Could not compare trunk main with remote — skipping trunk update This also caused `stackNeedsRebase` to always return true (since `IsAncestor("main", ...)` errors out), forcing an unnecessary rebase and force-push on every sync. Add a `BranchExists` check at the top of `fastForwardTrunk`. If the local trunk doesn't exist, return silently — there's nothing to fast-forward, and the remote tracking ref is sufficient for rebasing via git's DWIM resolution.
Configuration menu - View commit details
-
Copy full SHA for 8c2d9e3 - Browse repository at this point
Copy the full SHA 8c2d9e3View commit details -
remove silent prefix detection in init (#126)
* Remove silent prefix detection from args path in init When explicit branch names containing slashes were passed to `gh stack init` (e.g. `gh stack init myprefix/branch`), detectPrefix would silently extract the prefix and store it in the stack config. This caused `gh stack add otherbranch` to unexpectedly produce `myprefix/otherbranch` without the user ever opting in. Remove the automatic prefix detection from the args path so that explicit branch names are taken literally. Users who want a prefix should use `--prefix`. The interactive path (no args) continues to prompt for confirmation before setting a prefix. * Remove dead detectPrefix function and its tests After removing the silent prefix detection from the args path, detectPrefix has no production callers. Remove the function and its table-driven unit test to avoid maintaining unused code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for f8c0100 - Browse repository at this point
Copy the full SHA f8c0100View commit details -
ensure local trunk branch for required operations (#127)
* Ensure trunk branch exists locally before commands that need it When a user starts a stack after renaming their initial branch (e.g. `git branch -m newbranch`), the trunk branch (e.g. main) may not exist as a local branch. Commands that pass the trunk name to git operations like merge-base, rebase, or rev-parse then fail with: fatal: Not a valid object name main Add an `ensureLocalTrunk` helper that checks whether the trunk branch exists locally and, if not, fetches it from the remote and creates a local tracking branch. This mirrors the pattern already used in the checkout command for importing stacks. Commands updated: - modify: call ensureLocalTrunk before the linearity check in CheckStackLinearity, which uses IsAncestor(trunk, branch). This was the originally reported failure. - rebase: call ensureLocalTrunk after fetch and before fastForwardTrunk and the cascade rebase. git rebase requires a locally resolvable ref; the remote tracking ref alone is not sufficient. - trunk: call ensureLocalTrunk before CheckoutBranch so that `gh stack trunk` works even when trunk was never created locally. - checkout: refactor the existing inline BranchExists + CreateBranch block to use the shared helper. Also fix an incorrect comment in fastForwardTrunk that claimed "the remote tracking ref is sufficient for rebasing" — verified empirically that `git rebase main` fails when main has no local branch, even after fetching origin/main. Commands that were already safe and required no changes: - sync: fetches trunk explicitly and fastForwardTrunk guards with BranchExists - push, switch, navigate, unstack: do not reference trunk - add, submit: do not require trunk as a local git ref - view: handles IsAncestor errors gracefully (false positive is acceptable since rebase will fix it) * add check to avoid unnecessary remote selection prompt
Configuration menu - View commit details
-
Copy full SHA for 756002b - Browse repository at this point
Copy the full SHA 756002bView commit details -
* Save selected remote to gh-stack.remote git config Users with multiple git remotes are prompted to choose a remote on every gh stack operation, which is tedious. This adds the ability to persist that choice so it only needs to be made once. When a user interactively selects a remote (because multiple remotes exist and none is configured as a push default), they are now shown a Y/n follow-up prompt offering to save that remote for all future gh stack operations. If accepted, the choice is written to the local git config key `gh-stack.remote`, and instructions for changing or clearing it are printed. The saved remote is checked in `ResolveRemote` after the standard git push config keys (branch.<name>.pushRemote, remote.pushDefault, branch.<name>.remote) but before falling back to listing all remotes. This means per-branch git push configuration still takes precedence, and the --remote flag on individual commands continues to override everything. All commands that resolve a remote (push, submit, sync, rebase, checkout, link, modify, trunk) go through the shared `pickRemote` helper, so they all benefit automatically. Changes: - Add GetSavedRemote, SaveRemote, ClearRemote to the git Ops interface, defaultOps implementation, public wrappers, and MockOps - Check gh-stack.remote in ResolveRemote's priority chain - Move pickRemote from push.go to utils.go as a shared helper - Add save-remote confirmation prompt after interactive remote selection - Add unit tests for pickRemote save/decline/skip/override flows - Add integration tests for ResolveRemote with saved remote and precedence, and for the SaveRemote/GetSavedRemote/ClearRemote lifecycle * add error message for save failure Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 4c05e58 - Browse repository at this point
Copy the full SHA 4c05e58View commit details -
* flag for rebasing without trunk * update docs with new rebase flag
Configuration menu - View commit details
-
Copy full SHA for e45a88c - Browse repository at this point
Copy the full SHA e45a88cView 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.5...v0.0.6