Skip to main content

jj-workflow

Guidelines and procedures for using Jujutsu (jj) in KHI, including change management, workspace isolation, pushing commits with auto-generated bookmarks, addressing PR review feedback without squashing, and resolving conflicts incrementally from oldest to newest commit.

Source facts

Repository
GoogleCloudPlatform/khi
Last source activity
November 4, 2026 at 04:05
Detected SKILL.md language
English
Stars
2,087
Forks
100

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
jj-workflow
description
Guidelines and procedures for using Jujutsu (jj) in KHI, including change management, workspace isolation, pushing commits with auto-generated bookmarks, addressing PR review feedback without squashing, and resolving conflicts incrementally from oldest to newest commit.
# KHI Jujutsu (`jj`) Workflow Guidelines This guide outlines the standard version control workflow for working on the Kubernetes History Inspector (KHI) project using Jujutsu (`jj`). --- ## 1. Core Principles - **Prefer Jujutsu (`jj`) Commands**: Always use `jj` commands instead of raw Git commands whenever possible. - **Working Copy is Always a Change**: In Jujutsu, the working copy (`@`) is treated as an in-progress change/commit at all times. - **Describe vs. New**: - `jj describe -m "..."`: Updates the commit message of the _current_ change (`@`). It does not create a new commit. - `jj new`: Commits and freezes the current change, then creates a new, empty working-copy change (`@`) on top of it. - **Task Boundaries**: Always run `jj new` upon completing a logical unit of work or before switching tasks. - **Workspace Isolation**: Always make changes strictly within your assigned workspace. You may inspect or reference other workspaces, but never modify files or commit changes in another workspace. --- ## 2. Workspace Isolation > [!IMPORTANT] > **Never modify files or state in other workspaces.** > > - Inspecting or referencing other workspaces (e.g., viewing files or reading logs) is allowed. > - However, you must NEVER modify, edit, or create files in another workspace. > - All changes, commits, and development work must take place strictly within your assigned workspace. --- ## 3. Standard Development Flow ### Starting a New Change Before starting work on a new feature or bugfix, verify that your working copy is clean with `jj status`, then create a new change: ```bash # Create a new working-copy change jj new -m "feat(scope): short description" ``` ### Developing and Reviewing Changes Edit files as needed. Check your progress and inspect changes: ```bash jj status jj diff ``` Update the commit message as work evolves: ```bash jj describe -m "feat(scope): detailed message" ``` ### Testing and Formatting Before finalizing any commit or boundary, execute KHI test and verification commands: ```bash make pre-commit make lint-go && make lint-web make test-go && make test-web ``` ### Freezing the Change When the task is complete and verified: ```bash jj new ``` This freezes your completed change into the commit graph history (`@-`) and moves your working copy (`@`) to a new empty change. --- ## 4. Pushing Changes & Remote Bookmarks > [!IMPORTANT] > **Do not invent custom remote branch names manually.** > Always let `jj` generate and manage bookmark names automatically. When you need to push a change to the remote repository for review or PR creation: ```bash # Push the change at @; jj automatically creates and attaches a bookmark named push-<change_id> jj git push -c @ ``` - Jujutsu automatically assigns a unique bookmark name (e.g., `push-qpzqrvsmmnvr`) and pushes it to the remote Git repository (`origin`). - Use this auto-generated bookmark name as the head branch when opening a Pull Request on GitHub. - For stacked PRs involving multiple linear commits, push each commit to create its corresponding remote bookmark: ```bash jj git push -c <rev1> -c <rev2> ``` - If the change already has a tracked remote bookmark, update it with: ```bash jj git push --tracked ``` --- ## 5. Addressing PR Review Feedback (No Squashing) > [!IMPORTANT] > **Do NOT squash review fixes into the original commit (`jj squash` is forbidden here).** > Reviewers must be able to inspect incremental diffs across review rounds. Always preserve review iteration history. When review comments require code changes: 1. **Create a New Child Revision on the PR Commit**: Start a new change directly on top of the PR commit: ```bash # If @ is already the PR commit: jj new # Or target the PR commit/bookmark explicitly: jj new <pr-bookmark-or-commit> ``` 2. **Apply the Fixes**: Modify the source files to address the reviewer feedback. 3. **Verify and Format**: Run formatters and tests to ensure no regressions: ```bash make format-go && make format-web make test-go && make test-web ``` 4. **Set a Descriptive Commit Message**: ```bash jj describe -m "fix(scope): address review comments on XYZ" ``` 5. **Advance or Move the PR Bookmark to the New Commit**: Update the PR bookmark to track the newly created fix commit (`@`): ```bash # Option A: Advance the closest bookmark forward to @ jj bookmark advance # Option B: Move the specific PR bookmark to @ jj bookmark move <pr-bookmark-name> --to @ ``` 6. **Cascade Rebase for Stacked PRs (When Applicable)**: If this PR has child PRs stacked on top of it, linearly rebase the child PR's root commit onto the updated bookmark: ```bash jj rebase -s <first-commit-of-next-pr> -d <pr-bookmark-name> ``` Do NOT use merge commits in a stack. 7. **Push the Updated PR**: ```bash jj git push --tracked ``` The GitHub PR will automatically show the new incremental commit, allowing reviewers to verify changes easily. --- ## 6. Stacked PR Management & Post-Merge Rebasing KHI uses GitHub Stacked PRs (`gh stack`) and Merge Queue for development. ### Linear Stack Graph in Jujutsu Keep all PR commits strictly linear without branching or merge commits: `<base-branch>@origin -> rev1 (PR 1) -> rev2 (PR 2) -> rev3 (PR 3) ...` (where `<base-branch>` is `main` or an `epic/*` branch). Each PR commit has its own auto-generated bookmark (`push-xxxx`) pushed to `origin`. ### Post-Squash Merge Rebasing GitHub's Merge Queue merges PRs using the `SQUASH` method, resulting in a single squashed commit on `<base-branch>@origin` (e.g., `main@origin` or `epic/<name>@origin`). The original individual commit history of the merged PR is replaced on the base branch. When a bottom PR (e.g., PR 1) is squash-merged into `<base-branch>`: 1. **Fetch the Updated Remote**: ```bash jj git fetch --remote origin ``` 2. **Rebase Remaining Stack Commits onto `<base-branch>@origin`**: Rebase the root commit of the remaining unmerged PRs (e.g., PR 2) directly onto `<base-branch>@origin`: ```bash jj rebase -s <first-commit-of-remaining-bottom-pr> -d <base-branch>@origin ``` 3. **Abandon Old Pre-Squash Revisions**: Abandon the old local commits of the merged PR using Jujutsu revset syntax to keep the revision graph clean: ```bash jj abandon "<base-branch>@origin..<old-pr-bookmark-name>" ``` 4. **Push the Rebased Stack**: ```bash jj git push --tracked ``` --- ## 7. Conflict Resolution Workflow (Oldest to Newest) In Jujutsu, merge and rebase conflicts do not abort operations. Instead, conflicts are recorded as first-class states directly on the affected commits. > [!IMPORTANT] > **Always resolve conflicts starting from the oldest conflicted commit first.** > Resolving the oldest commit frequently resolves downstream conflicts automatically and prevents cascading conflict cycles. ### Step-by-Step Resolution Procedure 1. **Identify Conflicted Commits**: List all revisions currently in a conflicted state: ```bash jj log -r 'conflicts()' ``` 2. **Select the Oldest Conflicted Commit**: Examine the commit graph and pick the oldest (root-most) ancestor among the conflicted revisions. Let this be `<conflicted-rev>`. 3. **Spawn a Working Copy on the Conflicted Commit**: Create a new child revision directly on the conflicted commit: ```bash jj new <conflicted-rev> ``` The working copy (`@`) now contains the conflicting files with conflict markers (`<<<<<<<`, `>>>>>>>`, `%%%%%%%`). 4. **Resolve Conflict Markers**: Edit all conflicting files and resolve the markers manually to achieve the desired clean state. 5. **Verify the Resolution**: Run linters and tests to verify that the resolution builds cleanly and passes all test suites: ```bash make lint-go && make lint-web make test-go && make test-web ``` 6. **Squash the Resolution into the Conflicted Commit**: Once all tests pass, squash the working copy back into the parent commit (`<conflicted-rev>`): ```bash jj squash ``` This moves the clean, resolved content into `<conflicted-rev>`, clearing its conflicted state. 7. **Repeat for Remaining Downstream Conflicts**: Jujutsu automatically rebases any child commits on top of the resolved commit. Re-check for remaining conflicts: ```bash jj log -r 'conflicts()' ``` If any commits still have conflicts, repeat steps 2 through 6 for the next oldest conflicted commit until `conflicts()` is completely empty. --- ## 8. Pre-flight Checklist Before finalizing any task or pushing to a remote repository: - [ ] Worked strictly within the assigned workspace and made no cross-workspace modifications. - [ ] Executed `make pre-commit` to format all code and documentation files. - [ ] Passed all linters and tests (`make lint-go`, `make lint-web`, `make test-go`, `make test-web`). - [ ] For PR reviews: created a new incremental commit with `jj new` without squashing. - [ ] For PR reviews: advanced or moved the PR bookmark with `jj bookmark advance` or `jj bookmark move`. - [ ] For stacked PR reviews: cascade-rebased downstream stack commits with `jj rebase -s <next-pr-root> -d <pr-bookmark>`. - [ ] For conflict resolution: resolved from oldest to newest commit using `jj new` -> test -> `jj squash`.
View on GitHub