# jj > Jujutsu (jj) workflow guidance used in place of Git for commit/push, stacked work, status/log, diff/show, rebase, split/squash, abandon/restore, conflict resolve, bookmarks. Use when users mention jj/Jujutsu or ask how to do Git workflows in jj. - Author: Bede Carroll - Repository: bedecarroll/dotfiles - Version: 20260115200928 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/bedecarroll/dotfiles - Web: https://mule.run/skillshub/@@bedecarroll/dotfiles~jj:20260115200928 --- --- name: jj description: Jujutsu (jj) workflow guidance used in place of Git for commit/push, stacked work, status/log, diff/show, rebase, split/squash, abandon/restore, conflict resolve, bookmarks. Use when users mention jj/Jujutsu or ask how to do Git workflows in jj. --- # JJ Workflow (Canonical) ## Policy - For new PRs, use `jj push-new` (alias for `jj git push --change @-`) to create the bookmark and push it. - Do not run `jj git push` directly; use `jj push` for updates and `jj push-new` for new PRs. - Do not pre-create bookmarks for independent PRs. For stacked PRs, create a bookmark per layer so each PR has a stable head. - Avoid generating multiple new bookmarks for the same PR. If a bookmark already exists, move it and run `jj push`. - Only use `jj abandon` after confirming with the user; it is rare and usually indicates recovery from a bad state. - Enforce Conventional Commits for commit messages and PR titles. Format: `type(scope optional)!: subject`. - Allowed types: `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `build`, `ci`, `perf`. - Scope is optional; `!` marks breaking changes. - If the user supplies a non-conforming title/message, propose a compliant one and confirm before committing/creating a PR. - If the merge strategy is squash, the PR title becomes the commit message; keep it Conventional. ## Notes - `@` is the working-copy commit; `@-` is its parent. - `jj push` (alias for `jj git push @-`) pushes the bookmark(s) pointing at `@-`. If `@-` has no bookmarks, use `jj push-new` instead. - `jj push-new` (alias for `jj git push --change @-`) creates a new bookmark and pushes it. - `trunk()` resolves to the repository's trunk bookmark and avoids guessing `main` vs `master`; wrap it in single quotes for shell safety. - When a revset includes parentheses (like `trunk()`), single-quote it. ## Workflows Initialize / clone: - `jj git init [DESTINATION]` - `jj git clone [DESTINATION]` Create a new change from trunk: - `jj new 'trunk()'` Decide whether the work is independent or stacked: - Independent work must start from `trunk()` to avoid accidental stacking. - Stacked work intentionally builds on a prior change; each stack layer gets its own bookmark and PR. - Use an independent PR when the change does not depend on other unmerged work. - Use a stack when the overall effort is too large for one PR but can be split into self-contained, mergeable chunks. - Stack only when later changes rely on earlier unmerged work and reviewers benefit from smaller, focused slices. Check where I am: - `jj status` Check commit history: - `jj log` View diff for current change: - `jj diff` (defaults to `-r @`) Show full change details: - `jj show ` - Use `jj log -p -r ` for patch-view history. New commit (new PR): - `jj commit -m "type: message"` (scope optional: `type(scope): message`) - `jj push-new` - If this PR was already pushed, move the existing bookmark and use `jj push` instead. Independent PR (standalone) flow: - `jj new 'trunk()'` - Make changes → `jj commit -m "type: message"` - `jj push-new` - Create the PR with base `master` (or repo trunk) so GitHub shows only this change. Stacked PR flow (multiple dependent changes): - Create each change as a separate revision in a chain. - Create a bookmark for each layer (example names: `bede/1`, `bede/2`): - `jj bookmark create -r ` - Push each bookmark: - Move bookmark if needed: `jj bookmark move --to ` - `jj push` - Create PRs in order, setting the base of each PR to the previous layer’s bookmark/branch. Unwind an accidental stack (PR shows unrelated commits): - `jj git fetch` - Identify the intended change (bookmark or revision): `jj bookmark list` or `jj log -r ` - Rebase just that change onto trunk: - `jj rebase -r -A 'trunk()' --ignore-immutable` - Move the bookmark to the rebased change (use `@-` if it is the parent of the working copy): - `jj bookmark move --to @-` - Push the updated bookmark: - `jj push` - Ensure the PR base is trunk (update via `gh pr edit --base ` if needed). Add a commit to an existing PR/stack (reuse existing bookmark): - `jj commit -m "type: message"` (scope optional: `type(scope): message`) - `jj status` (identify the existing `push-...` bookmark for the current change) - If multiple `push-...` bookmarks are shown, ask which PR/bookmark to update. - `jj bookmark move --to @-` - `jj push` - If no bookmark exists yet, do not create one manually; use `jj push-new`. Amend current change content: - `jj squash` (move working-copy changes into parent) Split a change: - `jj split` Squash/merge changes in a stack: - `jj squash [--from ] [--into ]` Abandon a change: - `jj abandon [REVSET]` Restore a file to parent state: - `jj restore ` - Restore a file from trunk: - `jj restore --from 'trunk()' -- ` Resolve conflicts: - `jj resolve [FILESETS]...` Recover from a bad state (operation log): - Use when repo state is messed up (bad merges/conflicts/accidental rebase). - Prefer `jj op log` + `jj op restore` over manual rebases when unsure. - `jj op log` (see recent operations; each op snapshots repo state) - Optional preview: `jj --at-op= log` - `jj undo` (undo the most recent operation) - `jj redo` (redo the most recently undone operation) - `jj op restore ` (restore repo state to a specific operation) - `jj op revert ` (revert a specific earlier operation) Sync with trunk: - `jj git fetch` - `jj rebase -d 'trunk()'` Rebase a stack onto trunk (move a change and all its descendants): - `jj rebase -r :: -A 'trunk()' --ignore-immutable`