Shikanime Org jj Restack + Conflict Resolution
Rebase a jj stack (bookmarked commits above main) onto a moved trunk, then
resolve every conflict the move produced. jj restack in these environments is
an alias — jj config get aliases shows
restack = ["rebase", "--onto", "trunk()", "--source", "roots(trunk()..) & mutable()", "--simplify-parents"]
— so it rebases all mutable roots onto trunk. Where the alias is undefined,
the scoped equivalent is jj rebase -b <branch> --onto main@origin per
bookmark. This skill covers the full loop: restack → resolve → push.
When to Use
- Trunk moved (squash-landed PR, cascading rebase) and your stack must follow: "restack and resolve the conflicts".
- "Rebase my jj stack onto main and fix the conflicts."
- Post-restack
jj git pushfailsWon't push commit ... since it has conflicts— come here before improvising. - Multi-link stacks: resolve bottom-up so each fix's parent stays stable.
Prerequisites
- jj repo (
.jj/); the stack's bookmarks exist (jj bookmark list). - Trunk is current:
jj git fetch --remote originfirst, or you restack onto a stalemain@origin.
Procedure
Baseline.
cd ~/Source/Repos/github.com/<orga>/<repo> jj git fetch --remote origin jj bookmark list && jj log -r 'trunk()..mutable()' --limit 15Completion: bookmark set known; every stack rev visible.
Restack. Alias when defined, else scoped per bookmark:
jj config get aliases | grep -q restack \ && jj restack \ || jj rebase -b <branch> --onto main@originRebase auto-moves bookmarks — confirm with
jj bookmark listafter. Completion: no "skipped" lines for your revs.Converge via
sks-converge. Resolving conflicts (and any divergence the fetch reveals) is that skill's reusable loop: locate withconflicts()/divergent(), resolve per revision, repoint bookmarks. Loadsks-convergeand follow it; do not re-derive resolution here.Return to your working copy if
sks-convergemoved@(its Procedure A step 3):jj edit <original @ change-id>.Push gate.
sks-convergeexits pushable; re-assert here:jj log -r 'conflicts()' --no-graph # MUST print nothing jj git push --remote origin -b <branch>A restacked bookmark already on origin is rewritten non-FF: the push output reads
[move sideways from <old> to <new>]— expected shape, not an error. On this host push with--config signing.behavior=drop --config git.sign-on-push=false(key in no agent); GitHub squash-merge re-signs server-side.Hand off. Rewritten stack PRs land via
sks-land/sks-pr-workflow; leftover(empty)revs and stale workspaces aresks-gcterritory.
Pitfalls
- Marker dialect,
jj resolve --listlimits,jj editre-parenting — all resolution mechanics live insks-converge; load it rather than improvising. - Push rejects conflicts.
Won't push commit ... since it has conflictsis the gate doing its job; resolve, never bypass. [move sideways from X to Y]on push = bookmark moved non-FF by the restack; expected for an already-pushed branch.- Stale trunk. Restacking without
jj git fetchrebases onto oldmain@origin— wasted resolution work. - Shared working copy. The alias's
roots(trunk()..) & mutable()restacks every mutable root, including other sessions' WIP; with concurrent editors, prefer the scopedjj rebase -b <branch> --onto main@origin.
Verification
jj log -r 'conflicts()' --no-graph # empty
jj status # @ restored, no stray M files
jj bookmark list # bookmark on the rewritten rev
jj git push --remote origin -b <branch> # accepted, no conflict rejection
See also
sks-converge— the reusable conflict/divergence resolution loop this skill hands off to after the rebase.sks-dev-workflow— the landing gates this feeds; never force-push stack branches.sks-stack— isolate before resolving when the main checkout is crowded.sks-async— multi-link stacks whose streams each need this loop.sks-gc— reclaim empty revs and stale isolation workspaces afterwards.