Splitting a jj Changeset

Split the changeset `$ARGUMENTS` into smaller, focused units — safely, efficiently, and with user involvement at the right moments.

25 stars

Best use case

Splitting a jj Changeset is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Split the changeset `$ARGUMENTS` into smaller, focused units — safely, efficiently, and with user involvement at the right moments.

Teams using Splitting a jj Changeset should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/jj-split-changeset/SKILL.md --create-dirs "https://raw.githubusercontent.com/ComeOnOliver/skillshub/main/skills/RediSearch/RediSearch/jj-split-changeset/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/jj-split-changeset/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How Splitting a jj Changeset Compares

Feature / AgentSplitting a jj ChangesetStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Split the changeset `$ARGUMENTS` into smaller, focused units — safely, efficiently, and with user involvement at the right moments.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Splitting a jj Changeset

Split the changeset `$ARGUMENTS` into smaller, focused units — safely, efficiently, and with user involvement at the right moments.

If `$ARGUMENTS` is empty, ask the user which revset to split before proceeding.

## Table of Contents

1. [Core Safety Principle: Duplicate First](#1-core-safety-principle-duplicate-first)
2. [Workflow Overview](#2-workflow-overview)
3. [Inspect the Changeset](#3-inspect-the-changeset)
4. [Plan with the User](#4-plan-with-the-user)
   - 4.1 [How to group the changes](#41-how-to-group-the-changes)
   - 4.2 [What description each changeset should get](#42-what-description-each-changeset-should-get)
   - 4.3 [How to validate each changeset](#43-how-to-validate-each-changeset)
5. [Duplicate the Changeset](#5-duplicate-the-changeset)
6. [Split the Changeset](#6-split-the-changeset)
   - 6.1 [File-Path Split](#61-file-path-split-when-each-file-belongs-to-one-group)
   - 6.2 [Hunk-Level Split](#62-hunk-level-split-when-a-file-has-mixed-changes)
   - 6.3 [Ordering matters](#63-ordering-matters)
7. [Set Descriptions](#7-set-descriptions)
8. [Verify the Split](#8-verify-the-split)
   - 8.1 [Verify completeness](#81-verify-completeness--no-changes-lost)
   - 8.2 [Verify individual changesets](#82-verify-individual-changesets--stat-review)
   - 8.3 [Run user-defined validation](#83-run-user-defined-validation)
9. [Rebase Dependents](#9-rebase-dependents-if-needed)
10. [Clean Up](#10-clean-up)
11. [Key Commands Reference](#11-key-commands-reference)
12. [When to Prompt the User](#12-when-to-prompt-the-user)
13. [Limitations](#13-limitations)

---

## 1. Core Safety Principle: Duplicate First

**Never edit the original changeset directly.** Always duplicate it first, then work on the duplicate. This gives you a free undo — the original remains untouched until you're confident the split is correct.

```bash
# ALWAYS start here
jj duplicate <revset>       # Creates an identical copy; prints the new change ID
```

Only after the split is complete and verified should the original be abandoned:

```bash
jj abandon <original-revset>
```

This principle applies to every step below.

---

## 2. Workflow Overview

1. **Inspect** — understand what's in the changeset
2. **Plan with the user** — agree on groupings, descriptions, and validation criteria
3. **Duplicate** — create a safe working copy
4. **Split** — file-path-based or hunk-level
5. **Describe** — set meaningful descriptions on each resulting changeset
6. **Verify** — confirm no changes were lost, then run user-defined validation
7. **Rebase dependents** — ask the user if anything needs rebasing
8. **Clean up** — abandon the original

---

## 3. Inspect the Changeset

Before doing anything, understand what you're working with.

```bash
# Show the full diff with file names and stats
jj diff -r <revset> --stat
jj diff -r <revset>

# Show the changeset description and parents
jj log -r <revset>
```

Summarize for the user:
- How many files are changed
- Which files are logically related
- Whether there are clear groupings (e.g., "refactor" vs "feature" vs "tests")

---

## 4. Plan with the User

**Always ask the user three things before proceeding.**

### 4.1. How to group the changes

Present the file list and your suggested groupings, but let the user decide.

Example prompt:

> This changeset touches 8 files. I see what looks like three logical groups:
> 1. **Refactor**: `src/foo.rs`, `src/bar.rs` (signature changes)
> 2. **Feature**: `src/new_thing.rs`, `src/lib.rs` (new functionality)
> 3. **Tests**: `tests/test_new_thing.rs`, `tests/test_foo.rs`
>
> Does this grouping look right? Would you like to split differently?

**Mixed hunks within a single file:** If a file has changes belonging to different logical groups, flag this to the user. The agent can handle hunk-level splits without interactivity — see [6.2 Hunk-Level Split](#62-hunk-level-split-when-a-file-has-mixed-changes). Present the hunks from the file and ask the user which hunks belong to which group.

### 4.2. What description each changeset should get

Ask for commit messages. Suggest defaults based on the groupings, but let the user confirm or override.

### 4.3. How to validate each changeset

Ask the user how to verify that each split changeset is correct **beyond** diffstat review. Examples:

> How should I validate each split changeset? Some options:
> - **Build check**: `cargo build` / `cargo check` after each split
> - **Test suite**: `cargo test` (all tests, or a specific subset?)
> - **Lint/format**: `cargo clippy`, `cargo fmt --check`
> - **Diff review only**: just show me the diffs and I'll eyeball them
>
> You can specify different validation per group (e.g., "run tests for the feature changeset, diff review only for the refactor").

Store the validation plan — you'll execute it in [Step 8.3](#83-run-user-defined-validation).

---

## 5. Duplicate the Changeset

```bash
jj duplicate <revset>
# Note the new change ID from the output — this is your working copy
```

All subsequent operations target the **duplicate**, not the original.

---

## 6. Split the Changeset

Do **not** use `jj split -i` (interactive mode) — it opens an editor, which doesn't work in an agent context. Use either file-path-based splitting or the manual reconstruction approach below.

### 6.1. File-Path Split (When Each File Belongs to One Group)

`jj split -r <rev> <paths...>` divides a changeset into two:
- **First** changeset: contains only the changes to the specified paths
- **Second** changeset: contains everything else

To split into more than two groups, run `jj split` repeatedly on the remainder.

```bash
jj duplicate <original>
# Say this produces change ID: abc

# First split: extract the refactor files
jj split -r abc src/foo.rs src/bar.rs
# Output tells you the two new change IDs.
# The "remainder" changeset (everything except foo+bar) — say it's def.

# Second split: extract the feature files from the remainder
jj split -r def src/new_thing.rs src/lib.rs
# Now you have three changesets: refactor, feature, tests
```

### 6.2. Hunk-Level Split (When a File Has Mixed Changes)

When a single file contains hunks belonging to different logical groups, you cannot use `jj split -r <rev> <path>` because it moves the entire file. Instead, construct each changeset manually by creating empty changesets and writing the desired file contents into them.

**Strategy:** For each group, create a new empty changeset off the parent, then populate it — using `jj restore --from <duplicate>` for whole-file inclusions and direct file writes for partial-file inclusions.

```bash
jj duplicate <original>
# Say this produces change ID: dup

# Identify the parent of the duplicate
jj log -r 'dup-' --no-graph -T 'change_id'
# Say the parent is: parent

# --- Group 1: refactor (whole file src/bar.rs + some hunks from src/foo.rs) ---

# Create an empty changeset on the parent
jj new <parent>
# Now the working copy is a new empty changeset — say it's g1

# Restore whole files that belong entirely to this group
jj restore --from <dup> src/bar.rs

# For src/foo.rs, only some hunks belong here.
# 1. Read the file at the parent state (the "before")
# 2. Read the full diff from the duplicate to understand all hunks
# 3. Apply only the desired hunks to produce the correct file content
# 4. Write the result directly
jj diff -r <dup> src/foo.rs   # Examine hunks, decide which belong to group 1
# Write the file with only the group-1 changes applied:
cat > src/foo.rs << 'EOF'
... file contents with only the refactor hunks applied ...
EOF

# --- Group 2: feature (rest of src/foo.rs + src/new_thing.rs + src/lib.rs) ---

jj new <g1>
# New empty changeset — say it's g2

# Restore whole files
jj restore --from <dup> src/new_thing.rs src/lib.rs

# For src/foo.rs, apply the remaining hunks (the ones NOT in group 1).
# The starting state is g1's version of foo.rs (which already has the refactor hunks).
# Write the final version that includes both refactor + feature hunks:
cat > src/foo.rs << 'EOF'
... file contents with the feature hunks applied on top of g1 ...
EOF

# --- Group 3: tests (remaining whole files) ---

jj new <g2>
jj restore --from <dup> tests/test_new_thing.rs tests/test_foo.rs
```

**How to produce the partial file contents:**

1. Run `jj diff -r <dup> <path>` to see all hunks for the file.
2. Read the file at the parent state: `jj cat -r <parent> <path>`.
3. Determine which hunks belong to the current group (from the plan agreed with the user in [Step 4.1](#41-how-to-group-the-changes)).
4. Apply only those hunks to the parent-state content to produce the desired file.
5. Write the result to the working copy.

This is more work than file-path splitting, but it gives full hunk-level control without any interactive commands.

### 6.3. Ordering Matters

Think about the **dependency order** of the groups. If the feature changes depend on the refactor, extract the refactor first so it becomes the parent of the feature changeset. Both `jj split` and the manual approach create a parent→child chain.

---

## 7. Set Descriptions

Apply the descriptions agreed in [Step 4.2](#42-what-description-each-changeset-should-get):

```bash
jj describe -r <revset1> -m "refactor: update foo and bar signatures"
jj describe -r <revset2> -m "feat: add new_thing implementation"
jj describe -r <revset3> -m "test: add tests for new_thing and updated foo"
```

---

## 8. Verify the Split

Verification has two parts: **completeness** (no changes lost) and **correctness** (each changeset is valid on its own).

### 8.1. Verify Completeness — No Changes Lost

Use `jj interdiff` to confirm the combined result of the split matches the original:

```bash
jj interdiff --from <original-revset> --to <last-split-revset>
```

If the split is correct, this produces **no output** (empty diff). Any output means changes were lost or duplicated.

If `jj interdiff` is not available in your version, fall back to comparing raw diffs:

```bash
diff <(jj diff -r <original-revset>) <(jj diff -r <first-split> && jj diff -r <second-split> && jj diff -r <third-split>)
```

### 8.2. Verify Individual Changesets — Stat Review

Show the user the stat summary of each changeset:

```bash
jj diff -r <revset1> --stat
jj diff -r <revset2> --stat
jj diff -r <revset3> --stat
```

### 8.3. Run User-Defined Validation

Execute the validation plan from [Step 4.3](#43-how-to-validate-each-changeset). For each changeset, check out the state at that revision and run the agreed checks:

```bash
# Example: validate that the refactor changeset builds
jj new <revset1>
cargo check
# ... then validate the next changeset, etc.
```

If any validation fails, report the failure to the user and ask how to proceed — do not abandon the original or continue automatically.

Present a summary of all verification results and ask the user to confirm before proceeding.

---

## 9. Rebase Dependents (If Needed)

**Only after all verification passes and the user has confirmed**, check whether other changesets depend on the original:

```bash
jj log -r '<original-revset>+'
```

If there are dependents, ask the user which split changeset they should be rebased onto:

> The following changesets are children of the original:
> - `xyz` ("add benchmarks")
>
> Which split changeset should they be rebased onto?
> 1. `<revset1>` — "refactor: update foo and bar signatures"
> 2. `<revset2>` — "feat: add new_thing implementation"
> 3. `<revset3>` — "test: add tests for new_thing and updated foo"

Then rebase as directed:

```bash
jj rebase -s <dependent> -o <new-parent>
```

---

## 10. Clean Up

Once everything is verified and dependents are handled:

```bash
jj abandon <original-revset>
```

---

## 11. Key Commands Reference

| Command | Purpose |
|---|---|
| `jj duplicate <revset>` | Create a safe copy before any destructive operation |
| `jj split -r <revset> <paths...>` | Split by file paths (specified paths → first changeset, rest → second) |
| `jj restore --from <src> [paths...]` | Copy file states from one changeset into the current working changeset |
| `jj interdiff --from <a> --to <b>` | Show diff between two changesets (empty = identical) |
| `jj cat -r <revset> <path>` | Print a file's contents at a given revision |
| `jj describe -r <revset> -m "..."` | Set a changeset's description |
| `jj abandon <revset>` | Abandon a changeset (only after verifying the split) |
| `jj rebase -s <src> -o <dest>` | Rebase a changeset and its descendants onto a new parent |
| `jj diff -r <revset> --stat` | Show what a changeset changes (summary) |
| `jj diff -r <revset>` | Show full diff of a changeset |
| `jj log -r <revset>` | Show changeset metadata |
| `jj new <revset>` | Create a new empty changeset as a child |

---

## 12. When to Prompt the User

**Always ask before:**
- Deciding how to group changes ([4.1](#41-how-to-group-the-changes))
- Setting commit descriptions ([4.2](#42-what-description-each-changeset-should-get))
- Defining validation criteria for each changeset ([4.3](#43-how-to-validate-each-changeset))
- Proceeding after any validation failure ([8.3](#83-run-user-defined-validation))
- Rebasing dependent changesets ([9](#9-rebase-dependents-if-needed))
- Abandoning the original changeset ([10](#10-clean-up))

**Don't ask, just do:**
- `jj duplicate` — always safe
- `jj diff --stat` / `jj diff` — read-only inspection
- `jj log` — read-only inspection
- `jj interdiff` — read-only verification
- Running the agreed validation commands ([8.3](#83-run-user-defined-validation))

---

## 13. Limitations

- **No interactive commands.** Never use `jj split -i` or any command that opens an editor. Use file-path-based `jj split` for whole-file splits and the manual `jj new` + `jj restore` + file-write approach for hunk-level splits.
- **Hunk-level splits require care.** When manually applying hunks, verify the resulting file contents are correct. A mistake here is harder to spot than a wrong file-level grouping. The completeness check in [8.1](#81-verify-completeness--no-changes-lost) will catch lost or duplicated changes.

Related Skills

splitting-datasets

25
from ComeOnOliver/skillshub

Process split datasets into training, validation, and testing sets for ML model development. Use when requesting "split dataset", "train-test split", or "data partitioning". Trigger with relevant phrases based on skill purpose.

code-splitting-helper

25
from ComeOnOliver/skillshub

Code Splitting Helper - Auto-activating skill for Frontend Development. Triggers on: code splitting helper, code splitting helper Part of the Frontend Development skill category.

Changesets

25
from ComeOnOliver/skillshub

## Overview

Daily Logs

25
from ComeOnOliver/skillshub

Record the user's daily activities, progress, decisions, and learnings in a structured, chronological format.

Socratic Method: The Dialectic Engine

25
from ComeOnOliver/skillshub

This skill transforms Claude into a Socratic agent — a cognitive partner who guides

Sokratische Methode: Die Dialektik-Maschine

25
from ComeOnOliver/skillshub

Dieser Skill verwandelt Claude in einen sokratischen Agenten — einen kognitiven Partner, der Nutzende durch systematisches Fragen zur Wissensentdeckung führt, anstatt direkt zu instruieren.

College Football Data (CFB)

25
from ComeOnOliver/skillshub

Before writing queries, consult `references/api-reference.md` for endpoints, conference IDs, team IDs, and data shapes.

College Basketball Data (CBB)

25
from ComeOnOliver/skillshub

Before writing queries, consult `references/api-reference.md` for endpoints, conference IDs, team IDs, and data shapes.

Betting Analysis

25
from ComeOnOliver/skillshub

Before writing queries, consult `references/api-reference.md` for odds formats, command parameters, and key concepts.

Research Proposal Generator

25
from ComeOnOliver/skillshub

Generate high-quality academic research proposals for PhD applications following Nature Reviews-style academic writing conventions.

Paper Slide Deck Generator

25
from ComeOnOliver/skillshub

Transform academic papers and content into professional slide deck images with automatic figure extraction.

Medical Imaging AI Literature Review Skill

25
from ComeOnOliver/skillshub

Write comprehensive literature reviews following a systematic 7-phase workflow.