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

Multiple Rebase Conflicts

@  zq       empty
○  y          **feat-2**
○  unv
○  vw       Will conflict
○  xw
○  xl       Will conflict
│ ~
│ ○  vr       Base of merge-a and merge-b **base**
│ ○  r        Rebase here                          <-- here
│ ○  l        No idea why
├─╯
○  q         **main**
~

Warning

Rebase feat-2 on top of r.

Tip

jj rebase -s xl -o r

or

jj rebase -r xl:: -o r
@  zq       empty
×  y          **feat-2**
×  unv
×  vw       Will conflict
×  xw
×  xl       Will conflict
○  r        Rebase here                          <-- here
○  l        No idea why
│
~

Boom.

First Conflict

Warning

What’s the conflict in xl?

Tip

jj show xl
Created conflict in README.md:
    ...
   11   11: - Completing tasks. Click a tiny box and watch your task get a line
   12   12:   through it, wich is basically like deleting it.
       13: <<<<<<< conflict 1 of 1
       14: %%%%%%% diff from: qmyyoorn bdcd7f2b (parents of rebased revision)
       15: \\\\\\\        to: roulqqom 67bb45ac "Rebase here" (rebase destination)
  13   16: +:quit
  14   17: +:qw
  15   18: +:wq
  16   19: +:q!
  17   20: +:x
  18   21: +:exit
  19   22: +:how to quit this editor?
  20   23: +:emacs
  21   24: +:emacs help
       25: +++++++ xlkttytw e08dfcc6 "Will conflict" (rebased revision)
       26:
       27: - Filters. All, Active, Completed. Choose your poison.
       28:
       29: - Inline editing. Made a typo? Double-click and fix it. So cool!
       30: >>>>>>> conflict 1 of 1 ends

The conflict is in xl, but originated in r, its new base. Apparently I wrestled with Vim and mangled README.md. As an Emacs user, that’s embarrassing.

You could resolve the conflict in xl, but why keep messy Vim commands in README.md? Why not tidy up r directly?

Resolving The Conflict at Its Root

Let’s use the mini-workflow:

jj new r
jj restore -f r- README.md
jj squash
@ q           empty
│ ×  y          **feat-2**
│ ×  unv
│ ×  vw       Will conflict: deleted file
│ ○  xw
│ ○  xl       Will conflict: Vim
├─╯
○  r        Rebase here
○  l        No idea why
│
~

Cool! That fixed xl and the resolution propagated to xw.

Look what happened: you had a conflict in xl and solved it by editing its parent r, which had no conflicts at all! Git has nothing like this. It’s a small revelation: fixing a conflict without opening the conflicted file.

Second Conflict

There’s still a conflict in vw. What is it?

Added conflict feat-2.js:
        1: <<<<<<< conflict 1 of 1
        2: %%%%%%% diff from: xwzyvpnm c8dcd10f (parents of rebased revision)
        3: \\\\\\\        to: xwzyvpnm c8dcd10f (rebased revision)
        4: -import { useState } from "react";
        5: -import { Plus, Check, X } from "lucide-react";
        6: -
        [...]
      108: +++++++ vwqzzmtx 46b8d529 "Will conflict: deleted file" (rebased revision)
      109: import { useState } from "react";
      110: import { Plus, Check, X, Pencil } from "lucide-react";
      111:
      [...]
      309: >>>>>>> conflict 1 of 1 ends

Jujutsu tells you:

  • x deleted feat-2.js.
  • v tries to edit it (Pencil at line 110).

The root of conflict is the deletion of feat-2.js. Where did it happen?

jj log -r 'files("feat-2.js")'
×  y          **feat-2**
~  (elided revisions)
@  vw       Will conflict: deleted file
~  (elided revisions)
○  l        No idea why
○  q         main
│
~

feat-2.js was created in q. What about l?

jj show --summary l
    No idea why

D feat-2.js

Here’s the culprit! The message says it all: I had no idea what I was doing.

Warning

What if you remove that mistaken Change?

Tip

jj abandon l

All clear!

○  y          **feat-2**
○  unv
○  vw       Will conflict: deleted file
○  xw
○  xl       Will conflict: Vim
○  r        Rebase here

Amazing! Solving a conflict by deleting past commits!