Skip to main content

to navigate · Press ? for help

First-Class Conflict Handling

jj treats conflicts as first-class objects—stored in commits, not blocking errors that halt your workflow.

Git's Conflict Model

In git, conflicts block everything:

git merge feature
# CONFLICT: file.js

# Can't commit until resolved
git status
# both modified: file.js

# Must resolve before continuing
vim file.js
git add file.js
git commit

jj's Conflict Model

In jj, conflicts live in commits. You can continue working, view them, and resolve when ready.

jj merge feature
# Conflict recorded in @

# Can still work
jj status
# Shows conflicts

# Can commit @ with conflicts
jj describe -m "Merge with conflicts"
jj new

# Resolve later
jj resolve

Viewing Conflicts

git
git status
jj
jj status
Command comparison: git commands on the left, jj commands on the right
gitjj
git statusjj status

Resolving Conflicts

git
vim app.js
git add app.js
git commit
jj
vim app.js
jj resolve app.js
jj resolve --ours app.js
jj resolve --theirs app.js
Command comparison: git commands on the left, jj commands on the right
gitjj
vim app.jsvim app.js
git add app.jsjj resolve app.js
git commitjj resolve --ours app.js

Continuing with Conflicts

In jj, you can commit with conflicts and resolve later:

# Merge creates conflict
jj merge feature

# Commit the conflict state
jj describe -m "Merged with conflicts in app.js"
jj new

# Continue working on other files
vim other.js
jj describe -m "Work on other file"
jj new

# Come back to resolve later
jj edit --change <commit-with-conflict>
jj resolve
NOTE:

This is powerful for complex merges—resolve conflicts in batches, not all at once.

Conflict Materialization

When you have conflicts, jj shows them in files:

# jj creates conflict markers
$ cat app.js
<<<<<<< Left
const x = 1;
=======
const x = 2;
>>>>>>> Right

But the conflict is also stored in commit metadata:

$ jj show @
Conflict in app.js:
  Left: abc (our change)
  Right: def (their change)
  Base: 123 (original)

Multiple Conflicts

git
git merge feature
jj
jj merge feature
jj resolve file1
jj resolve
jj describe -m "Partial merge"
jj new
Command comparison: git commands on the left, jj commands on the right
gitjj
git merge featurejj merge feature

Abandoning Merges

git
git merge --abort
jj
jj abandon @
jj op undo
Command comparison: git commands on the left, jj commands on the right
gitjj
git merge --abortjj abandon @

Rebase Conflicts

Even with jj's automatic rebasing, conflicts can occur:

jj rebase -d main@origin
# Conflict in app.js

# Resolve and continue
jj resolve app.js
jj rebase --continue

But since jj auto-rebases descendants, you only resolve once:

git
git rebase -i HEAD~5
git add .
git rebase --continue
jj
jj edit old-commit
jj resolve
Command comparison: git commands on the left, jj commands on the right
gitjj
git rebase -i HEAD~5jj edit old-commit
git add .jj resolve
git rebase --continue

Conflict Resolution Tools

git
git mergetool
jj
jj resolve --tool
jj resolve --ours file.js
jj resolve --theirs file.js
Command comparison: git commands on the left, jj commands on the right
gitjj
git mergetooljj resolve --tool

Visualizing Conflicts

# See which files have conflicts
jj status

# Show conflict details
jj show @

# Show just conflicts
jj diff --conflict

Try It Yourself

# Create a conflict scenario
# Terminal 1
jj init repo1
cd repo1
echo "original" > file.txt
jj describe -m "Initial"
jj new

# Terminal 2
jj init repo2
cd repo2
echo "original" > file.txt
jj describe -m "Initial"
jj new

# Make diverging changes
# Terminal 1
echo "change1" > file.txt
jj describe -m "Change 1"
jj new

# Terminal 2
echo "change2" > file.txt
jj describe -m "Change 2"
jj new

# Now try to merge in Terminal 1
# (after somehow importing Terminal 2's changes)
# You'll get a conflict

jj resolve --edit file.txt
# Choose "change1" or "change2" or both

Key Takeaways

  • Conflicts are stored in commits, not blocking errors
  • jj resolve marks conflicts as resolved
  • Can commit with conflicts and resolve later
  • jj resolve --ours / --theirs for quick resolution
  • Auto-rebasing means resolve conflicts once
  • jj op undo to abandon problematic merges

Next Steps

Finally, let's look at advanced workflows and tips for jj power users.

Try It Yourself

Loading terminal...

Progress stored locally · No account needed · Open source