Skip to main content
jj-git

Rebasing and Editing History

Step 8 of 12

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

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

Squashing Commits

jj
jj squash @- -m "Combined message"
Command comparison: git commands on the left, jj commands on the right
gitjj
git rebase -i HEAD~3jj squash @- -m "Combined message"

Reordering Commits

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

Moving Commits (Rebase)

jj
jj rebase -d @-
Command comparison: git commands on the left, jj commands on the right
gitjj
git rebase --onto new-base old-base branchjj rebase -d @-

Abandoning Commits

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:

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

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

$
$
$

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.

Practice Exercises

0/4 completed

  1. 1Create a conflict in a file
  2. 2View conflict markers in the file
  3. 3Resolve the conflict
  4. 4List and abandon a conflict