Releases: bos/jj-stack
Release list
v0.1.5
jj-stack 0.1.5 completes merges in one command, including through a merge queue, and explains what still blocks a PR that has approvals and passing checks.
Breaking changes
jj-stack mergeno longer returns as soon as GitHub queues the PRs. It waits for the merge to finish, then fetches trunk, removes the merged changes from your local stack, rebases the rest, and updates their PRs, so a queued merge no longer needs a separatejj-stack sync. Scripts that relied on the early return must pass--no-waitand runjj-stack sync <head-change-id>in a later step once GitHub has merged.
Highlights
- While a merge queue is working,
jj-stack mergeshows each PR's queue position, GitHub's time estimate, and the state of the queue's checks. Press Ctrl-C to stop waiting, or pass--no-waitto return as soon as GitHub accepts the request; neither cancels it. Rerun the samejj-stack mergeto resume waiting, or runjj-stack sync <head-change-id>after GitHub finishes. - If GitHub removes a PR from the merge queue,
jj-stack mergestops without changing anything locally, reports GitHub's reason, links to the checks on the queue's temporary merge commit (they never appear on the PR's own Checks tab), and names the next step:jj-stack sync <head-change-id>when a lower PR already merged, otherwise the samejj-stack mergeagain. jj-stack viewandjj-stack listreport GitHub's merge state separately from review decisions and checks. An approved PR with passing checks can showmerge blocked, for example while review threads remain unresolved, andreview requiredappears when GitHub still requires a review.jj-stack view --verboselists unresolved review threads and failed or pending checks with links. In JSON, changes gainmerge_state_statusand thereview_requiredstatus, andview --verbose --jsonaddsmerge_detailswithunresolved_threadsandchecks, ormerge_details_errorwhen the details could not be read.- If your working copy is on a change that just merged,
jj-stack sync(including the automatic sync aftermerge) moves it to a new empty change on trunk before removing the merged change, instead of stopping and asking you to runjj new 'trunk()'first. Only a different workspace sitting on the merged change still stops the sync.
Fixes
- After a merge queue lands the bottom of a stack and drops the PR above it, GitHub leaves that PR at its submitted commit on its old base.
jj-stack syncnow rebases the remaining changes onto trunk and retargets that PR, instead of stopping with "Imported pull request heads no longer form the expected stack". - When someone pushed to your PR branch outside jj-stack and GitHub then merged the PR,
jj-stack syncstill stops rather than delete your local change, but its hint now names the commit that merged and how to resolve it: compare the PR's files withjj diff -r <change-id>, then eitherjj abandon <change-id>and runjj-stack cleanup, or runjj-stack unstack --local <change-id>and submit again. The old hint blamed yourtrunk()revset. jj-stack submitexplains when GitHub refuses to add a PR with auto-merge enabled to a stack and tells you to disable auto-merge on that PR first, instead of a generic retry hint that led back to the same failure.- When a repository rule rejects the PR-branch push, such as an org ruleset that blocks force pushes or requires signatures, the error shows Git's report of each rejected ref and GitHub's reason and says that no PR branch changed, instead of printing the underlying push command line.
- Recovery hints fill in the selected head's short change ID or the linked PR number when the command knows it, instead of placeholders such as
HEADorCHANGE, and use<change-id>and<pr>otherwise, matching the guides.jj-stack unstackreports an untrusted saved link with the same explanation, hint, and exit code as the other commands. - Several errors now say what happened and what to do next. An undescribed change names
jj describe; immutable, merge-commit, and not-on-trunk changes gain hints; the signed-commit stop explains that merging can discard signatures and that a choice is only needed when the repo allows several methods; and the closed-PR stops insubmitall namejj-stack cleanup --pull-request <pr>. Authentication failures mentionGITHUB_TOKEN,GH_TOKEN, and yourghlogin rather thanGITHUB_TOKENalone. - Other jj-stack commands in the repo no longer fail with
jj-stack submit is already running in this repowhilesubmit --edithas your editor open or a--describe-withhelper is running. Submit reads the stack and GitHub again once the editor closes; if the stack changed meanwhile, it stops before pushing anything, with the usual--resume-edithint. --helpoutput has its color highlighting back and is available even when jj configuration cannot be read. Settingui.color=alwaysin jj no longer prevents jj-stack from reading your configuration.jj-stack view --verboseshows a PR's details only when it has unresolved threads or check results to report, is blocked without any, or could not be inspected, instead of one block per healthy PR. Its advisory rows name the head's short change ID rather than a full 32-character ID.- Terminal hyperlinks are underlined so they are recognizable as links.
jj-stack mergeno longer prints aTrunk:line in its result; each action row already names the base branch.
v0.1.4
jj-stack 0.1.4 improves recovery after GitHub rebases a stack, gives more complete submit previews, and adds recovery guidance to JSON reports.
Highlights
jj-stack mergeno longer requires an explicit method for an unsigned stack when the repo allows several methods: it prefers rebase, then squash, then a merge commit. Setjj-stack.merge_methodor pass--methodto choose another allowed method. Stacks containing signed commits still require an explicit choice when several methods are allowed; merge queues choose their own method.jj-stack submit --dry-runnow shows the planned PR, branch, and GitHub stack membership changes, making it easier to check what a submit will do before publishing.- JSON reports now include
needs_submitandneeds_syncon changes,head_change_idon stacks, and optionalreasonandrepairtext for problems. Scripts can distinguish unpublished local edits from PR review status and display the same recovery guidance as the terminal output.
Fixes
- After GitHub's Rebase stack action,
jj-stack sync <head-change-id>can recover the rebase even if trunk has advanced again. It checks against the base GitHub actually used and retains your original jj change IDs. Status output also keeps the sync instruction visible when an unchanged submitted child sits above the affected stack. jj-stack synccan close a PR outside a GitHub stack whose submitted commit reached trunk through an external fast-forward push. It no longer gets stuck trying to retarget a PR to a branch that already contains its work.- If PR publication succeeds but a later stack or comment update fails, jj-stack now reports what finished and gives a retry command for the remaining work. After a sync has already rebased your changes, the hint directs you to finish publication or cleanup instead of repeating a sync that may have nothing left to do.
- When joining stacks with conflicting overview comments,
jj-stack submitnow stops before changing PR branches, pull requests, or stack membership. The dry run reports the same conflict. jj-stack doctornow detects missing push permission on the selected repo, so a clone that cannot submit PR branches fails the setup check with an explanation instead of failing on its first push.- Non-ASCII change descriptions and bookmark names are decoded correctly on Windows and other systems whose locale encoding is not UTF-8.
- If GitHub's merge-queue lookup fails,
jj-stack mergenow reports that error before requesting a merge, avoiding a misleading rejection from an attempted direct merge.
Documentation
- The guides now walk through moving a change between submitted stacks while keeping its PR, recovering from sync conflicts, and cleaning up PRs whose local changes have been abandoned.
v0.1.3
jj-stack 0.1.3 focuses on making changes made on GitHub safe to recover from. It can now finish partial stack merges, bring reviewer commits into your local stack, and explain when a PR branch changed without silently overwriting work.
Breaking changes
- jj-stack now requires
jj0.45.1 or newer, so that it can make use of the newconvergecommand injj. Checkjj --versionand upgradejjbefore installing this release if needed. - If a submit fails after you edit its pull request descriptions, retry with
jj-stack submit --resume-edit <saved-file>. The oldjj-stack submit --edit <saved-file>form no longer works;--editby itself always starts a new editing session. - If you validate the JSON from
vieworlist, accept the newbranch_movedstatus. It means a PR branch contains commits that do not match either your local change or the version you last submitted. Thecommentedstatus has been removed from the schema because jj-stack never produced it.
Highlights
- When a PR branch is updated on GitHub by a reviewer, another checkout, or another tool,
jj-stack viewandjj-stack listnow show that clearly. To keep the new commits, runjj-stack checkout --pull-request <pull-request>and follow the printedjj convergeorjj squashcommand. To discard them and publish your local version, runjj-stack relink --replace-remote <pull-request> <change-id>, then submit the stack again. synccan now finish after GitHub merges only the bottom of a stack, even if you have continued editing the pull requests above it. It rebases those local changes onto the new trunk and updates the remaining pull requests without discarding your edits.- You can now finish a merge by naming any pull request in the stack:
jj-stack sync --pull-request <number-or-url>. jj-stack finds and syncs the complete local stack, including when that pull request has already merged.
Fixes
syncnow recognizes more common post-merge states, including a merged change that became empty after you rebased it yourself and a partial stack merge followed by newer commits on trunk. It also checks whether the remaining PR branches changed on GitHub before changing your local history.cleanupno longer deletes a PR branch that another open or reopenable pull request still uses as its base. When you usecleanup --close, jj-stack first retargets the pull request to trunk so deleting its branch does not make it impossible to reopen.submitandrelinknow stop before acting on an abandoned change, a change with no content, or a change with no description. The error points to the change and tells you whether to select a visible change, add or abandon content, or runjj describe.- In a fresh clone,
checkout --pull-requestno longer fails because jj treats fetched PR branches as immutable.doctor --fixalso removes those bookmarks and any leftovers from an interrupted checkout or sync. - A stack whose top change is being edited in another jj workspace is no longer mistaken for a shorter stack, preventing a submit from dropping that top change from the GitHub stack.
- Very long change titles no longer make
submitfail with an invalid branch name. If you customizejj-stack.branch_prefix, invalid values now fail early with a useful error, and changing the prefix does not prevent updates to pull requests created with the old one. - If GitHub rejects a label or reviewer after creating a pull request, jj-stack keeps the pull request linked to its local change so a normal retry can finish the submit. Pull request descriptions based on templates or multiline change descriptions also update correctly again.
mergenow honorsjj-stack.merge_methodwhen GitHub cannot report which merge methods the repository allows. Stacks based directly on a merge commit at trunk can also be submitted, merged, and synced again.- GitHub failures now include the useful part of GitHub's response and distinguish rate limits from authentication problems. A broken stack or missing pull request that you are not working with no longer prevents jj-stack from finding unrelated valid stacks.
v0.1.2
jj-stack 0.1.2 makes submitted changes easier to review and safer to update. It adds visible
revision history and CI status while preserving text edited directly on GitHub.
Highlights
jj-stack submitnow maintains a pull request comment with recent submitted revisions and
direct links to each version and its diff from the preceding version.- Pull request descriptions and stack overviews edited on GitHub are preserved by later submits.
Generated descriptions still refresh automatically while they remain unchanged. - If an edited submit fails, jj-stack keeps the editor file and prints a retry command. Pass the
saved path tojj-stack submit --edit FILEafter resolving the failure. jj-stack viewandjj-stack listnow show whether GitHub checks passed, failed, or are still
pending. JSON output exposes the same rollup aspr.checks.- Pull request references in interactive terminal output are now clickable links. Plain and
redirected output remain link-free.
Fixes
- Submitting the remaining changes after abandoning a previously submitted change can now repair
the GitHub stack grouping without closing or forgetting the abandoned change's pull request. - Revision-history comments include the version just submitted even while GitHub's force-push
timeline is still catching up. - Deleted tracked bookmarks and conflicted bookmarks no longer prevent jj-stack from observing a
local stack. relinknow identifies a pull request's original change ID after stack surgery and gives a
concrete recovery command instead of suggesting an unsafe replacement link.- Saved-editor recovery commands and terminal hyperlinks now render correctly on Windows.
Documentation
- New guides explain how bookmarks affect stack selection, how to invoke the tool as
jj stack,
and how jj-stack compares with jj-spr, jj-gh, and gh stack.
v0.1.1
Full Changelog: v0.1.0...v0.1.1
v0.1.0
What's Changed
- drop trailing period by @bos in #6
- refactor: remove leftover status error alias by @bos in #15
- deps: add dependency cooldown by @bos in #26
- ci: bump astral-sh/setup-uv from 6 to 7 by @dependabot[bot] in #21
- ci: bump actions/download-artifact from 4 to 8 by @dependabot[bot] in #22
- ci: bump actions/upload-artifact from 4 to 7 by @dependabot[bot] in #23
- ci: bump actions/checkout from 4 to 6 by @dependabot[bot] in #24
- build(deps-dev): bump pytest from 8.4.2 to 9.0.3 in the uv group across 1 directory by @dependabot[bot] in #25
- ci: bump the github-actions group across 1 directory with 2 updates by @dependabot[bot] in #38
- deps: update hatchling requirement from >=1.29.0 to >=1.30.1 in the python-dependencies group across 1 directory by @dependabot[bot] in #40
- ci: bump the github-actions group across 1 directory with 3 updates by @dependabot[bot] in #43
- deps: bump the python-dependencies group across 1 directory with 4 updates by @dependabot[bot] in #44
New Contributors
- @dependabot[bot] made their first contribution in #21
Full Changelog: https://github.com/bos/jj-stack/commits/v0.1.0