Skip to main content

to navigate · Press ? for help

Rebasing and Editing History

jj makes editing history safe and automatic—no more manual conflict resolution from git commit --amend.

The Problem with Git

In git, editing old commits is risky:

# Edit commit from 3 steps ago
git rebase -i HEAD~3
# Manually edit, save, exit

# All subsequent commits have conflicts
# Have to resolve each one manually

jj's Solution: Automatic Descendant Rebasing

When you edit an old commit in jj, all descendants automatically rebase. No manual intervention needed.

Editing Old Commits

git
git rebase -i HEAD~3
git add .
git commit --amend
git rebase --continue
jj
jj edit --change abc123
vim file.js
jj new
Command comparison: git commands on the left, jj commands on the right
gitjj
git rebase -i HEAD~3jj edit --change abc123
git add .vim file.js
git commit --amendjj new
git rebase --continue

Squashing Commits

git
git rebase -i HEAD~3
jj
jj squash @- -m "Combined message"
jj squash -r 'descendants(@, 2)' -m "One commit"
Command comparison: git commands on the left, jj commands on the right
gitjj
git rebase -i HEAD~3jj squash @- -m "Combined message"

Reordering Commits

git
git rebase -i HEAD~3
jj
jj rebase -s abc -d def
Command comparison: git commands on the left, jj commands on the right
gitjj
git rebase -i HEAD~3jj rebase -s abc -d def

Moving Commits (Rebase)

git
git rebase --onto new-base old-base branch
jj
jj rebase -d new-base
jj rebase -s 'descendants(abc, 5)' -d new-base
Command comparison: git commands on the left, jj commands on the right
gitjj
git rebase --onto new-base old-base branchjj rebase -d new-base

Abandoning Commits

git
git reset --hard HEAD~1
jj
jj abandon @-
Command comparison: git commands on the left, jj commands on the right
gitjj
git reset --hard HEAD~1jj abandon @-

Undo Any Operation

jj keeps an operation log—nothing is ever truly lost:

git
git reflog
git reset --hard HEAD@{1}
jj
jj op log
jj op undo
Command comparison: git commands on the left, jj commands on the right
gitjj
git reflogjj op log
git reset --hard HEAD@{1}jj op undo

Practical Example

Let's say you made 5 commits and want to edit the second one:

# Current history
@  Commit 5
◉  Commit 4
◉  Commit 3  ← Want to edit this one
◉  Commit 2
◉  Commit 1

# Edit commit 3
jj edit --change commit3

# Now @ is commit 3
@  Commit 3
◉  Commit 2
◉  Commit 1

# Make your changes
vim file.js

# Finalize the edit
jj describe -m "Updated commit 3"
jj new

# Commits 4 and 5 auto-rebased!
@  (new working copy)
◉  Commit 5 (auto-rebased)
◉  Commit 4 (auto-rebased)
◉  Updated commit 3
◉  Commit 2
◉  Commit 1
NOTE:

This automatic rebasing is one of jj's killer features. No more manual conflict resolution when editing history.

Splitting Commits

git
git reset HEAD~1
git add file1
git commit -m "Part 1"
git add file2
git commit -m "Part 2"
jj
jj edit @-
jj restore file2
jj describe -m "Part 1"
jj new
jj describe -m "Part 2"
jj new
Command comparison: git commands on the left, jj commands on the right
gitjj
git reset HEAD~1jj edit @-
git add file1jj restore file2
git commit -m "Part 1"jj describe -m "Part 1"
git add file2jj new
git commit -m "Part 2"jj describe -m "Part 2"

Safe History Editing

jj never loses data:

  • Every operation is recorded in the operation log
  • jj op undo reverses any operation
  • jj op restore <id> restores to any previous state
  • Abandoned commits remain until explicitly deleted

Try It Yourself

# Create 3 commits
echo "a" > a.txt
jj describe -m "Add A"
jj new

echo "b" > b.txt
jj describe -m "Add B"
jj new

echo "c" > c.txt
jj describe -m "Add C"
jj new

# Edit the middle commit
jj edit @-

# Change B
echo "b2" > b.txt

# Finalize
jj describe -m "Add B (updated)"
jj new

# Commit C auto-rebased!
jj log

Key Takeaways

  • Editing old commits auto-rebases descendants
  • jj edit moves @ to target commit
  • jj squash combines commits
  • jj rebase -d moves commits to new base
  • jj op undo reverses any operation
  • History editing is safe and reversible

Next Steps

Now let's explore jj's first-class conflict handling.

Try It Yourself

Loading terminal...

Progress stored locally · No account needed · Open source