Repository navigation
Tags
Tags
git stack get to pull down someone's stack, git stack doctor to check… … your setup, and gh-stack 0.3 support ## Breaking - **git-stack now needs gh-stack v0.3.0 or later.** gh-stack 0.3 keeps one stack file shared by every worktree instead of one per worktree, and it refuses to run (`cannot migrate stack catalogs: existing backup differs`) when an older git-stack has left per worktree files behind. git-stack now reads and writes only the shared file and moves any per worktree file into it the first time it runs, so stacks show up the same in every worktree. With an older gh-stack every command stops and tells you to upgrade. ## New - **`git stack get <pr|url|branch>`** (alias `git get`) pulls a pull request and the rest of its stack down so you can work on it, i.e. reviewing someone's stacked PRs no longer means creating and tracking each branch by hand. A PR in a stack on GitHub brings the whole stack; one that isn't brings the PR and the open PRs it's based on. Nothing is rebased or pushed. Agents get it as `stack_get`. Thanks @mvalipour! - **`git stack doctor`** checks git, gh, its login, gh-stack and its version, git-stack's aliases, whether a newer git-stack is out, and inside a repository that your stacks are in good shape (no half finished restack, no tracked branches that have gone, no empty branch in the middle of a stack). Every problem says what to do about it, and `--fix` sorts out what it can: installs or upgrades gh-stack, sets missing aliases, updates git-stack, moves old per worktree stack files across and forgets branches that are gone. Agents get it as `stack_doctor`, which also works outside a repository. - **Submit stops at an empty branch in the middle of a stack.** gh stack can't open a PR for a branch with no commits of its own, so rather than failing halfway through the push, submit now stops before pushing anything and suggests reordering it to the top, popping it or adding a commit. - **`git stack log short` marks branches that need a restack** (thanks @mvalipour). ## Fixed - **Sync no longer leaves already merged commits in your PRs when local main can't move.** If the local trunk couldn't be fast forwarded (an uncommitted file in the worktree that has main checked out, say), sync carried on restacking onto the old main, so the next submit opened PRs that still had commits already merged. Sync and the cleanup after it now use `origin/main` when the local one can't be moved, and still tell you main wasn't updated. ## After upgrading Upgrade gh-stack and fix anything left over from 0.2 in one go: ```sh git stack doctor --fix ```
submit syncs first when a PR in the stack has merged, so the next PR … …up doesn't carry the merged commits A bug fix. If a PR lower in your stack had merged and you ran `git ss` before syncing, gh stack skipped the merged branch and based the new PR on trunk, but your local branch was still sitting on the merged commits, so the new PR showed those as well as its own (and submit claimed it had "created" the merged PR too). The only thing telling submit a branch had merged was the flag gh stack writes to its metadata file, which gh stack only sets during its own submit, i.e. too late. ## Fixed - **`git stack submit` syncs first when a PR in the stack has merged.** It now reads merged from the PR list it fetches anyway, and when any branch of the stack has merged it runs the normal sync before pushing anything: the merged branch goes, the ones above are restacked onto trunk, and the submit carries on from what's left. What the sync did is printed above the submit lines. If you were on the merged branch itself, a whole stack submit picks up from the rest of the stack; `git ss --down` on it says there's nothing left. `--dry-run` can't sync, so it names the branches and leaves them out of the plan. Agents get the same from `stack_submit`; its result now carries `merged` (the branches) and `sync` (what the sync did).
git stack log short, log long and --stack, so a quick look at the tre… …e doesn't wait on GitHub A small one. `git stack log` was the only way to see your stacks, and it always went to GitHub for PR state even when all you wanted was the shape of the tree. Thanks to @mvalipour for this one, his first contribution. ## New - **`git stack log short`** draws the same tree with just the branch names, one line each. It only reads local git, so it never touches the network. `git stack log long` is the full tree, named explicitly. - **`stack.log.short`** (`git config --global stack.log.short true`) makes plain `git stack` and `git stack log` show the short tree by default; `git stack log long` still gets you everything. - **`--stack` / `-s`** on `log`, `log short` and `log long` only shows the current branch's stack, which keeps a repo with lots of stacks readable. On a trunk it shows every stack on that trunk. On a branch that isn't in a stack it shows them all and says so. Agents get the same with `current_stack: true` on `stack_view`.
Fold, pop, undo and four more commands, so nothing needs gh stack mod… …ify any more This one is mostly about changing a stack after you've built it. Until now a few of those jobs still sent you to `gh stack modify` and a manual restack; they're all git-stack commands now, and there's an undo for when one of them does something you didn't expect. ## New - **`git stack fold`** merges the current branch into the one below it, one branch and one PR. `--keep` keeps the current branch's name and PR instead. Nothing needs restacking. - **`git stack pop`** takes the current branch out of its stack and deletes it, leaving its changes staged on its parent (like `git reset --soft`). The branches above are restacked without it. - **`git stack undo`** reverses the last git-stack command that changed local state; run it again to step further back, up to 20 commands. It covers everything that rewrites branches (create, modify, absorb, restack, reorder, move, fold, pop, untrack, init, sync, a local rename) and never touches GitHub, so a submit or merge clears the history. It's per worktree, so an undo in your checkout won't reverse what an agent did in another one. `--list` shows what it would put back. - **`git stack create --insert`** puts a new branch right above the current one instead of only at the top, and restacks the ones above onto it. - **`git stack untrack`** stops tracking a branch and everything above it without touching the branches; `--only` takes just that one out and closes the gap. - **`git stack rename`** renames the current branch, here and on GitHub, keeping its PR attached. `--local` keeps it to your machine. - **`git stack pr`** opens the current branch's PR in your browser (or prints the URL when piped). - **`git stack update`** now shows what's in every release you're skipping, and brings what `git stack install` set up (aliases, completion, the agent skills) up to date with the new binary. Fold and pop close the PR they leave behind at your next submit, with a comment pointing at where the work went. Agents get all of these as MCP tools. ## Fixes - Absorbing a change that deletes lines no longer refuses with "this is a bug in stack_absorb". - Stacks are kept in each worktree's own stack file, and submit works from whichever worktree has the stack checked out. - Sync no longer restacks a merged branch it decided to keep. ## After upgrading If you set up aliases with `git stack install`, updating from v0.3.1 adds the new ones (`git fold`, `git pop`, `git undo` and the rest) for you. Anything older, run `git stack install` once.
git stack update now keeps your install up to date too, and continuin… …g a restack that stopped on a signing failure works again on git 2.56. Before this, updating swapped the binary but left everything `git stack install` set up as it was, so the skill kept describing the old release, new aliases never showed up and the completion script went stale until you ran install again. Now once the new binary is in place, `git stack update` hands over to it to refresh whatever install set up before (aliases, completion, the MCP registration if the binary moved, and the skills) without asking. It only touches what you installed in the first place, leaves an alias you've pointed elsewhere alone, and only prints what it changed. The skill now installs for Codex as well as Claude Code, each only if you have that agent's config directory. Also fixed: when a restack stopped because a commit couldn't be signed, `git stack continue` broke on git 2.56 (it'd go on to report a conflict that wasn't there). It now finishes the pick itself again, on 2.56 and on older versions. ## After upgrading The update that gets you to v0.3.1 is still run by the old binary, which doesn't know how to do the refresh. So run `git stack install` once after this update to pick up the Codex skill and anything else that's stale; from then on `git stack update` does it for you.
This release adds absorb, reorder, move and init, so fixing a commit … …lower down or changing the shape of a stack no longer means dropping back to gh stack, plus submit --down for sending just the bottom of a stack for review. ## New ### `git stack absorb` Fixing a review comment on the third PR down used to mean `git down` twice, `git modify -p`, `git top`, and getting the hunk selection right by hand. Now you stage the fixes and run `git absorb` (or `git ab`), and each run of changed lines goes into the commit in the stack that last changed those lines. That commit and everything above it gets rewritten (messages and authors kept), then the branches above are restacked. It doesn't push. ``` ❯ git absorb pkg/app/sync.go:120-125 into 7ac32ef Give up on a webhook after five attempts (billing-webhook-retries) pkg/app/sync.go:300 into 4f21abc Version the billing webhook payload (billing-webhook-schema) README.md:12 not absorbed; no commit in this stack changed those lines ? Absorb 2 hunks into 2 commits? [Y/n] ``` On a terminal you see the plan and get asked first; `--dry-run` just shows it and `--force` skips the question. It goes by lines, not meaning, so lines no commit in the stack touched (and new or deleted files) stay staged, and a run of changes spanning two commits' lines goes to the newer one rather than being split. The old tips are printed, and the README has the recipe for putting things back if it picked the wrong commit. Agents get it as `stack_absorb`. ### `git stack reorder` Changes the order of the branches in the stack you're on. On a terminal it shows the stack as a small list (`j`/`k` to move the cursor, `J`/`K` or shift with the arrows to move a branch, enter to apply); otherwise pass the new order as arguments, bottom to top. A conflict stops just like a restack, and `git abort` puts the old order back along with the branches. GitHub can't reorder a stack in place, so if it already has PRs the next `git ss` dissolves it on GitHub and creates it again in the new order. The PRs stay the same, but the stack's number changes. ### `git stack move` Takes the current branch, and everything above it, out of its stack and puts it on top of another stack or onto a trunk as a new stack (which can be a different trunk, e.g. moving a stack from `main` to `develop`). `--only` moves just that branch and leaves the ones above behind. Without `--onto` you get the checkout picker, showing only the places it can actually go. ``` ❯ git move --onto main --only ✔ Moved billing-webhook-alerts from billing-webhook-schema onto main (new stack) billing-webhook-retries stays on billing-webhook-schema ``` Same as reorder, the next `git ss` sorts out the stacks on GitHub, and its notices say what it did with each one. ### `git stack init` (alias `track`) Tracks branches you already have (e.g. ones you made with plain git) as a new stack. It only records the stack; nothing is committed, rebased or checked out, so if a branch isn't sitting on the one below it you're told to run `git restack`. The alias is `git track` since git won't let an alias replace its own `git init`. ``` ❯ git track search-index search-api search-ui ✔ Tracking search-index, search-api, search-ui on main ``` Reorder, move and init are `stack_reorder`, `stack_move` and `stack_init` for agents, so they can reshape a stack without shelling out. ### `git stack submit --down` Thanks to @StillAyo for this one. `git stack submit --down` submits the current branch and everything below it, and `git stack submit <branch>` does the same up to the named branch, leaving the branches above alone. Handy for getting the bottom of a stack reviewed while you keep working on the top. gh stack can only submit a whole stack, so here git-stack pushes those branches itself (still with `--force-with-lease`, so it won't overwrite commits someone else pushed), creates any missing PRs and links them into the stack on GitHub. gh stack's editor isn't available on that path, so new PRs take their titles from their commits unless you pass `--ai`. Plain `git ss` is unchanged. Agents get it through `down` and `branch` on `stack_submit`. ## After upgrading The new aliases (`git absorb`, `git ab`, `git reorder`, `git move` and `git track`) are installed by `git stack install`, so run it once to pick them up.
`git stack sync` brings your uncommitted changes along when it moves … …you off a merged branch, and cleans up worktrees whose directory you deleted. If you were on a branch whose PR had merged with any uncommitted change at all, sync kept the branch and told you to commit or stash first, even when git would have carried the change across a switch fine. Sync now switches to trunk the way `git switch` does, brings along what git can carry (untracked files too) and tells you; it only keeps the branch when the switch would overwrite something, and names those files. Sync also notices worktrees whose directory was deleted by hand, runs `git worktree prune` for them and says which it forgot, so their merged branches get cleaned up like any other instead of being kept forever. Locked worktrees are left alone, but you'll be told to `git worktree unlock` if the directory has gone.
Commit signing failures no longer hang the MCP server, and create, mo… …dify and restack tell you which key to unlock instead of leaving things in a mess. If you sign commits with an SSH key that isn't loaded into ssh-agent, an agent calling `stack_create` could hang forever, because ssh-keygen was asking for the passphrase on a terminal nobody could see. Without a terminal, git and anything it runs (ssh-keygen, gpg's pinentry, git's credential prompt) now fail straight away instead; the CLI in a terminal still prompts like before. That failure now comes back as a `signing_failed` error from `git stack create`, `git stack modify` and `git stack restack`, with the `ssh-add` line for your key (or a gpg check for openpgp) and the option of turning signing off for the repo, rather than git's stderr under "unknown". A failed commit in `git stack create` (a signing failure or a pre-commit hook saying no) also undoes the branch it made, so your changes stay staged and you can just run create again. A restack stopped by signing is no longer reported as a conflict, and `git stack continue` gets past it once the key is loaded.
`git stack log` shows a spinner while it fetches pull requests, so it… … no longer looks like it's hung. When the PR cache has gone stale, `git stack log` asks GitHub for every PR before drawing anything, which in a big repo is a noticeable pause with nothing on screen. That fetch now gets its own "Fetching pull requests…" step with a spinner (only when the cache actually needs refreshing), and `git stack submit` gets the same when it checks which PRs already exist. Ctrl-C on it now stops log or submit there, rather than submit carrying on and pushing.
Merge now refuses while a stack's checks are failing or still running… …, `git stack log` shows what's actually on each branch, and the terminal gets links, titles and status. ## Changed `git stack merge` used to only check the PRs were open and ready, and left CI to GitHub's branch rules. Those only block on required checks, so in a repo without any a stack with a failing lint or a test still running would merge happily. Merge now looks at the checks on every PR it's about to merge and refuses if any have failed (listing each PR and its failing checks), or asks you to wait if some are still running. Nothing is merged in either case. If you relied on merging with red or pending checks, fix them and `git stack submit` again, or pass `-f` / `--force` to merge anyway (GitHub's required checks still apply). If the checks can't be read at all, merge carries on with a notice rather than blocking you. For agents, `stack_merge` gets a `force` param and the refusal lists the checks so the agent can fix them or ask you first. ## New - `git stack log` shows each PR's title, then the branch's own commits (newest ten, then a count of the rest), so you can tell which branch holds which work without opening the PR. It's all local, so it's still quick. `stack_view` gets the commits too. - Every PR number and URL printed to a terminal is now a clickable link (underlined, keeping its usual colour), including in notices, errors, gh stack's output and the checkout picker. Under tmux you need its hyperlinks feature turned on; the README says how. - The window title shows what git stack is doing while a step runs (e.g. "git stack: Updating main") and goes back to what it was when it's done. Terminals that support OSC 7501 also get a proper status, i.e. working, waiting on you for a prompt or conflict, done or failed. Set `GIT_STACK_NO_TERMINAL_STATUS=1` to turn both off. ## Fixes - `git stack sync` no longer says "Synced, nothing to do" when it couldn't move a branch. A briefly held git lock (a status script's `git status`, say) is now retried properly, and if a lock or anything else still stops a branch moving, sync finishes everything else and then tells you which branch wasn't updated and why (exit 1). A checked out trunk is fast forwarded even with uncommitted changes, like `git pull`; if your changes are in the way it names the files and gives you the stash command to run. - When trunk has diverged from the remote, sync's "Reset it to the remote?" question no longer draws over a running spinner.
PreviousNext