Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rebasing

Reset your progress

To reset your progress, run:

curl https://s2p2.github.io/jj-for-everyone/reset.sh | bash -s rebase
cd ~/jj-tutorial/repo-bob

We are in Bob's repo.

cd ~/jj-tutorial/repo-bob

When Bob tries to push his new commit, it fails, just like it did for Alice.

jj bookmark move main --to @-
jj git push

The solution is to fetch the remote changes first.

jj git fetch

Bob's log now shows that his changes and Alice's have diverged:

@  ztyvwqll bob@local 2025-07-22 21:29:52 93f27644
│  (empty) (no description set)
○  smswwyok bob@local 2025-07-22 21:29:27 main?? main@git git_head() e583fa6e
│  Add submission instructions
│ ◆  twywpklt alice@local 2025-07-22 21:27:24 main?? main@origin 606959ce
╭─┤  (empty) Merge code and documentation for hello-world
│ │
│ ~
│
◆  quolxwkk bob@local 2025-07-22 21:22:22 8d538390
│  Document hello.py in README.md
~

Unlike Alice, who created a merge commit, Bob prefers a linear history. He will rebase his changes on top of Alice's. The jj rebase command moves commits from one "base" to another.

Bob specifies the destination (-d or --destination) for his commit: the remote main bookmark.

jj rebase -d main@origin

The log now shows a straight line, with Bob's commit directly following Alice's:

@  ztyvwqll bob@local 2025-07-22 21:30:38 e911e4c7
│  (empty) (no description set)
○  smswwyok bob@local 2025-07-22 21:30:38 main* git_head() 002bd1179
│  Add submission instructions
◆  twywpklt alice@local 2025-07-22 21:27:24 main@origin 606959ce
│  (empty) Merge code and documentation for hello-world
~

By rebasing, Bob has rewritten history. His commit now descends from Alice's. Now he can push:

jj git push

Merge vs. Rebase

Both are valid ways to integrate divergent changes. Here's a hopefully balanced overview of the main trade-off:

AdvantageDisadvantage
MergePreserves history exactly as it happened.Can result in a tangled, hard-to-read history.
RebaseResults in an easy-to-read, linear history.Rewrites history, obscuring the original order.