Skip to content

feat(server): add jj commit, push and PR workflows - #20753

Draft
THEjacob1000 wants to merge 5 commits into
pingdotgg:mainfrom
THEjacob1000:feat/jj-workflow
Draft

THEjacob1000 wants to merge 5 commits into
pingdotgg:mainfrom
THEjacob1000:feat/jj-workflow

Conversation

@THEjacob1000

@THEjacob1000 THEjacob1000 commented Oct 17, 2026 •

Copy link
Copy Markdown

Problem

Native status doesn't let a jj thread commit, publish its bookmark or open/check out a PR. Git mutations can target the wrong workspace or move a shared base bookmark. Stays dormant until #20756.

Change

JjStackedAction connects native commit, remote operations and PR preparation. Commit uses jj commit then advances the selected bookmark, and selected paths are literal filesets. Push targets one bookmark. Pull fast-forwards the bookmark and rebases the empty @ onto it, keeping its change id, description and edits; a diverged bookmark or non-empty @ asks you to rebase in jj. PR creation reuses #20752's step, and checkout imports the source ref as a child commit in a native workspace.

From @omarshaarawi's review: committing with @ mid-stack picks the nearest feature bookmark and never moves or pushes main, a description already on @ is kept (a message is generated only when it's empty), pull rebases instead of jj new so edits can't be orphaned, and a conflicted @ is refused. A failed first push to a new remote now gets the same guidance Git does. Includes @knocking4thcylinder's managed-bookmark protections and @omarshaarawi's shared-driver fix.

Known gaps: jj commits don't run Git hooks (surfaced in the commit dialog by #20754), and automatic pull doesn't apply to jj repos, only the Pull action.

Scope and approval

Approval is pending in #18468. Commits 1 to 6 are dormant on their own, #20756 is the one that turns jj on, and #20755 (idle workspace cleanup) sits on top so it can wait until the rest lands. Tracks #1126, the originals #11373, #11382, #11383, #11384, and ports #13816, #16380. @gergesh's port was a reference.

GitHub can't create stacked PRs from a fork, so the diff carries the PRs below. Review the top commit only.

Verification

Against a local bare remote: bookmark create, a selected-file commit leaving the other file in @, a mid-stack commit that kept the descendant, main and the existing description, conflict refusal, push and pull, diverged-remote refusal and a first push. Hosted publish and PR create/checkout weren't exercised because they need real GitHub writes.

Screenshots are from the integrated stack before the latest rebase onto current main. After rebasing, the stack was re-verified with the automated tests and the process comparison; the manual pass wasn't repeated.

Native controls and web workflow evidence
Scenario Result
Native jj workflow controls (inspection only) Native jj workflow controls
Native bookmarks and workspace sheet (inspection only) Native bookmark and workspace sheet
Native client interaction (inspection only) recording
Mid-stack commit retained description Mid-stack commit and prewritten description
Conflict refusal Conflicted commit refused
Divergent remote refusal Divergent bookmark sync refused
Missing local-remote transport Missing local bare repository refused

@omarshaarawi

Copy link
Copy Markdown

Three bugs, all reproduced on 0.46:

  1. With main <- x1(@) <- x2[feat], resolveWorkspaceRefName takes the last bookmarked row of heads(::@ & bookmarks())::@, which is main. Commit then runs jj bookmark set main -r @- and pushes main (JjStackedAction.ts:155, JjStatus.ts:50-66).
  2. jj commit -m <generated> replaces a description the user already wrote on @ (JjStackedAction.ts:425-430). Only generate a message when @ has none.
  3. Auto-pull checks clean, then runs jj new <bookmark>. Edits in between land on the orphaned change and vanish from disk, and a described empty @ gets orphaned on every pull (JjRemotes.ts:641). jj rebase -r @ -d <bookmark> keeps the user's change.

Smaller: commit is allowed on a conflicted @.

The exact: quoting, file: partial commits, diverged-remote refusal and PR checkout as a child commit all held up.

@THEjacob1000
THEjacob1000 force-pushed the feat/jj-workflow branch 2 times, most recently from 6259a32 to d53ad87 Compare October 19, 2026 18:00
THEjacob1000 and others added 5 commits October 20, 2026 06:45
Co-authored-by: Лев Федорец <152093961+knocking4thcylinder@users.noreply.github.com>
Co-authored-by: Лев Федорец <152093961+knocking4thcylinder@users.noreply.github.com>
Co-authored-by: Omar Shaarawi <16183117+omarshaarawi@users.noreply.github.com>
…vcs kind

Co-authored-by: Лев Федорец <152093961+knocking4thcylinder@users.noreply.github.com>
Co-authored-by: Лев Федорец <152093961+knocking4thcylinder@users.noreply.github.com>
@omarshaarawi

Copy link
Copy Markdown

Rechecked at 9bc3914 with jj 0.46. main mid-stack, keeping the @ description, and pull rebasing @ are fixed, and I ran all three. One major left:

  • The typed commit message is still dropped when @ has a description (JjStackedAction.ts:428-431). Say an agent ran jj describe -m "wip", then the user types a real message in the commit dialog. The commit lands as "wip". With featureBranch it's worse: the bookmark is named from the typed text (:271-296) while the commit keeps the agent's text. JjStackedAction.test.ts:309-319 now asserts the drop and docs/internals/jujutsu.md documents it. Keeping the description is right when the dialog is empty. The order should be input.commitMessage?.trim() || change.description.trim() || generated.

Minor:

  • JjRemotes.ts:676 rebase -r @ still splits unbookmarked children. With main <- @(empty) <- x2 and the remote ahead, @ moves onto the new main and x2 stays on the old one as a sibling. -s @ keeps them together.
  • JjRemotes.ts:659-667 refuses Pull on any non-empty @, so one file an agent touched blocks Pull where git's fast-forward pull works on a dirty tree. jj rebase -r @ already handles that, so it only needs to refuse when aheadCount > 0.
  • The two snapshotting jj diff -r @ calls at :110-123 still run concurrently. I couldn't make it fail in 20 runs, so I'm only noting it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants