Help users identify, understand, and resolve conflicts in jj repositories. Use when user mentions 'conflict', 'resolve conflicts', 'merge conflict', 'conflicted commits', '2-sided conflict', or encounters conflict-related errors.
/plugin marketplace add edmundmiller/dotfiles/plugin install jj@dotfiles-pluginsThis skill is limited to using the following tools:
This skill helps you identify and resolve conflicts in jj repositories, with special emphasis on safely using jj restore with path specifications.
When jj encounters a conflict, it:
jj log)"2-sided conflict": Two versions of the same content that can't be automatically merged
"2-sided conflict including 1 deletion": One side deleted a file/content, the other modified it
.gitignore after they were already trackedjj log -r 'conflicts()'
This shows all commits with unresolved conflicts. Look for the × marker.
jj status
If you're in a conflicted commit, this will show:
Warning: There are unresolved conflicts at these paths:
.obsidian/workspace.json 2-sided conflict including 1 deletion
jj edit <conflicted-commit-id>
jj diff
The jj resolve command is purpose-built for conflict resolution:
# Navigate to conflicted commit
jj edit <commit-id>
# List all conflicts
jj resolve --list
# Accept parent's version (side 1) - "ours"
jj resolve --tool :ours <path>
# Accept child's version (side 2) - "theirs"
jj resolve --tool :theirs <path>
# Use interactive merge tool (if configured)
jj resolve <path>
When to use:
:ours vs :theirs)The jj restore command can restore files from any commit:
# Navigate to conflicted commit
jj edit <commit-id>
# Restore SPECIFIC path from parent
jj restore --from @- <path>
When to use:
--from can be any revision):ours in resolve)This is the most important safety rule when using jj restore:
# ❌ DANGEROUS - Restores ALL files from parent
# This will LOSE ALL CHANGES in the current commit!
jj restore --from @-
# ✅ SAFE - Restores ONLY the specified path
# All other changes in the commit are preserved
jj restore --from @- .obsidian/
jj restore --from @- src/config.rs
Why this matters:
jj restore operates on ALL filesFor complex conflicts, you can edit the conflict markers directly:
jj edit <commit-id>
# Edit files with conflict markers
# Remove markers and keep desired content
jj diff # Verify your resolution
Conflict markers look like:
<<<<<<<
Content from side 1 (parent)
%%%%%%%
Common ancestor content
+++++++
Content from side 2 (child)
>>>>>>>
For complex resolutions, jj recommends creating a resolution commit:
# Create new commit on top of conflicted one
jj new <conflicted-commit-id>
# Resolve using any method above
jj resolve --tool :ours <path>
# Review the resolution
jj diff
# Squash resolution back into parent
jj squash
Benefits:
Situation: Parent commit deleted files (e.g., added to .gitignore), but child commits still have changes to those files.
Example: You added .obsidian/ to .gitignore and untracked it in commit oo, but 13 descendant commits still had .obsidian/ changes.
Conflict message:
.obsidian/workspace.json 2-sided conflict including 1 deletion
Resolution: Accept the deletion by restoring from parent
# Method 1: Using jj resolve (more semantic)
jj edit <conflicted-commit>
jj resolve --tool :ours .obsidian/
# Method 2: Using jj restore (equally correct)
jj edit <conflicted-commit>
jj restore --from @- .obsidian/
For multiple commits:
# Process each conflicted commit
for commit in $(jj log -r 'conflicts()' --no-graph -T 'change_id.short(4)'); do
jj edit "$commit"
jj restore --from @- .obsidian/
done
Situation: Both parent and child modified the same lines in a file.
Resolution options:
jj resolve --tool :ours or :theirsjj resolve <path> (if configured)Situation: One side renamed a file, the other modified it.
Resolution: Choose which version to keep, potentially applying changes from other side manually.
| Aspect | jj resolve | jj restore --from @- <path> |
|---|---|---|
| Purpose | Conflict resolution | Generic file restoration |
| Semantic clarity | :ours/:theirs explicit | Less explicit (must know parent/child) |
| Merge tools | Supported | Not supported |
| Flexibility | Limited to conflict resolution | Can restore from any revision |
| Safety | Only operates on conflicted files | MUST specify paths or affects all files |
Both are correct for accepting deletions, but resolve is more semantically clear.
Before resolving conflicts:
jj restore --fromjj diff to verify changes before and after resolutionjj status to confirm conflict is resolvedjj restore --from @- without paths unless you intend to reset entire commitThis documents a real scenario that illustrates the critical importance of path specification:
.obsidian/ to .gitignore in commit oo.obsidian/ files in that commit: jj file untrack .obsidian/.obsidian/ changesjj rebase -r 'oo..@' -d ooEach conflict shows:
.obsidian/workspace.json 2-sided conflict including 1 deletion
This means:
oo): Deleted .obsidian/ files.obsidian/ files# ❌ WRONG - This was tried first
jj edit <commit-id>
jj restore --from @- # No path specified!
# Result: ALL files restored from parent
# - All task files: DELETED
- All document changes: LOST
# - Only .obsidian/ should have been affected, but EVERYTHING was reset
Why this failed: Without a path argument, jj restore --from @- restores every file from the parent, effectively undoing all changes in the commit.
# ✅ CORRECT - Specify the path
jj edit <commit-id>
jj restore --from @- .obsidian/ # Path specified!
# Result: Only .obsidian/ restored from parent
# - Task files: PRESERVED ✓
# - Document changes: PRESERVED ✓
# - .obsidian/ conflicts: RESOLVED ✓
Or using jj resolve (more semantic):
jj edit <commit-id>
jj resolve --tool :ours .obsidian/
# Get list of conflicted commits
jj log -r 'conflicts()'
# Process each one with PATHS SPECIFIED
for commit in oymp zzyv knzl xlxr lutt xznz uvnk zosw vzxv utmq xtsk qvot pqnr; do
echo "Resolving $commit"
jj edit "$commit"
jj restore --from @- .obsidian/ # ← The critical path argument
done
# Verify all conflicts resolved
jj log -r 'conflicts()' # Should return empty
The difference between these two commands is losing all your work vs safely resolving conflicts:
jj restore --from @- # ← Danger: ALL files
jj restore --from @- .obsidian/ # ← Safe: ONLY specified path
Always specify the path when resolving conflicts with jj restore.
jj log -r 'conflicts()'
jj status
jj edit <commit-id>
jj resolve --tool :ours <path> # Accept parent's version
jj resolve --tool :theirs <path> # Accept child's version
jj edit <commit-id>
jj restore --from @- <path> # Accept parent's version for PATH ONLY
jj diff
jj status
jj log -r 'conflicts()' # Should not include current commit
Rebasing often creates conflicts:
jj rebase -r <commits> -d <destination>
# Check for new conflicts
jj log -r 'conflicts()'
# Resolve as needed
Always resolve conflicts before pushing:
# Check for unresolved conflicts
jj log -r 'conflicts() & mine()'
# If any found, resolve them first
# Then proceed with push
Conflicts can appear when updating stacked PRs:
jj rebase -d main
# Resolve any conflicts
jj restore --from @- <conflicted-path>
# Update PRs
jj spr update
Invoke this skill when you encounter:
jj log outputjj restore safely.gitignore after being trackedCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.