From b2463d694cf7c1dc0cf7d0b20ba5b4503620bc27 Mon Sep 17 00:00:00 2001 From: muloka <256166+muloka@users.noreply.github.com> Date: Sun, 12 Apr 2026 00:04:28 -0400 Subject: [PATCH] feat(commit-commands-jj): add ancestor check, post-merge cleanup, and absorbed change detection Add safety checks to /finish and /sync skills: - /finish Option 1: ancestor check warns about stacked changes before push - /finish Option 1: post-merge cleanup abandons local ancestors after squash-merge - /sync: detect absorbed changes after fetch, offer to abandon instead of conflicting rebase --- plugins/commit-commands-jj/commands/finish.md | 27 +++++++++++++++---- plugins/commit-commands-jj/commands/sync.md | 12 ++++++++- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/plugins/commit-commands-jj/commands/finish.md b/plugins/commit-commands-jj/commands/finish.md index e41d30c..5e35cff 100644 --- a/plugins/commit-commands-jj/commands/finish.md +++ b/plugins/commit-commands-jj/commands/finish.md @@ -57,7 +57,19 @@ What would you like to do? ### Option 1: Push and create PR (most common) -1. Ensure a bookmark exists on the target change: +1. **Ancestor check before push.** Before creating the bookmark, check for non-empty changes between trunk and the target that are NOT the target itself: + ```bash + jj log -r 'ancestors(TARGET) & ~ancestors(trunk()) & ~TARGET' --no-graph + ``` + If any exist, warn the user: + ``` + This PR will include N ancestor change(s) not part of this work: + - : + They'll be merged into trunk with the PR. + ``` + Let the user decide whether to squash them into the target first or push them separately. + +2. Ensure a bookmark exists on the target change: ```bash # Check for existing bookmark jj log -r --no-graph -T 'bookmarks' @@ -67,12 +79,12 @@ What would you like to do? jj bookmark create -r ``` -2. Push the bookmark: +3. Push the bookmark: ```bash jj git push --bookmark --allow-new ``` -3. Create the PR: +4. Create the PR: ```bash gh pr create --title "" --body "$(cat <<'EOF' ## Summary @@ -86,9 +98,14 @@ What would you like to do? )" ``` -4. Output the PR URL. +5. Output the PR URL. + +6. **Post-merge cleanup.** After a successful `gh pr merge`, before syncing, abandon all local changes that were ancestors of the PR branch (between trunk and the bookmark), since they're now in trunk via the squash-merge: + ```bash + jj abandon 'ancestors(TARGET) & ~ancestors(trunk())' + ``` -5. Then: Workspace cleanup (Step 4). +7. Then: Workspace cleanup (Step 4). ### Option 2: Squash into trunk (local merge) diff --git a/plugins/commit-commands-jj/commands/sync.md b/plugins/commit-commands-jj/commands/sync.md index a7d0de1..6382d1e 100644 --- a/plugins/commit-commands-jj/commands/sync.md +++ b/plugins/commit-commands-jj/commands/sync.md @@ -25,7 +25,17 @@ description: Fetch from remote and rebase the current change onto trunk Sync fetches the latest remote state and rebases your current work onto trunk. This is the jj equivalent of `git pull --rebase`. 1. Fetch from the remote: `jj git fetch` -2. Rebase onto trunk: `jj rebase -d main@origin` +2. **Detect absorbed changes.** Before rebasing, check for non-empty local changes above the old trunk that may already be included in a squash-merged PR: + ```bash + jj log -r 'ancestors(@) & ~ancestors(trunk()) & ~@' --no-graph + ``` + If any exist and would conflict when rebased onto the new trunk, list them and offer to abandon rather than forcing a rebase that produces conflicts: + ``` + These N change(s) appear to be absorbed by a squash-merge now in trunk: + - <change-id>: <description> + Abandon them? (They're already in trunk via the PR merge.) + ``` +3. Rebase onto trunk: `jj rebase -d main@origin` - If that fails (e.g., remote is not named `origin` or branch is not `main`), fall back to `jj rebase -d trunk()` 3. Check for conflicts: `jj log -r 'conflicts()' --no-graph -T 'json(self) ++ "\n"'` - If conflicts exist, report them clearly so the user can resolve them