Remix.run Logo
steveklabnik 9 hours ago

The "you don't need to worry about resolving conflicts" thing is confusing when you hear it with words, so let me show you what it looks like in practice.

Let's say I have two branches off of trunk. They each have one commit. That looks like this (it looks so much nicer with color, I'm going to cut some information out of the default log so that it's easier to read without the color):

    @  vvxvznow 
    │  (empty) (no description set)
    │ ○  uuowqquz 
    ├─╯  foo
    │ ○  uvlpytpm 
    ├─╯  bar
    ◆  lwywpyls trunk
    │  feat: blah blah blah
So both `foo` and `bar` are on top of trunk, and I'm also working on a third branch on top of trunk (@). Those vvxv and such are the change ids, and you can also see the named trunk there as well.

Now, I fetch from my remote, and want to rebase my work on top of them: a `jj git fetch`, and then let's rebase `foo` first: that's `jj rebase uu -o trunk` (you only need uu instead of uuowqquz because it's a non-ambiguous prefix, just like git). Uh oh! a conflict!

    @  vvxvznow
    │  (empty) (no description set)
    │ ×  uuowqquz (conflict)
    │ │  foo
    │ ◆  tswtuqmu
    ├─╯  chore: whatever
    ~  (elided revisions)
    │ ○  uvlpytpm
    ├─╯  bar
    
Note that jj did not put us into a "hey there's a conflict, you need to resolve it" state. It just did what you asked: it rebased it, there's a conflict, it lets you know.

So why is this better? Well, for a few reasons, but I think the simplest is that we now have choice: with git, I would be forced to deal with this conflict right now. But maybe I don't want to deal with this conflict right now: I'm trying to update my branches in general. Is this conflict going to be something easy to resolve? In this case, it's one commit. But what if each of these branches had ten commits, with five of them conflicted and five not? It might be a lot of work to fix this conflict. So the cool thing is: we don't actually have to. We could continue our "let's rebase all the branches" task and rebase bar as well. Maybe it doesn't have a conflict, and we'd rather go work on bar before we come back and deal with foo. Heck, sometimes, I've had a conflicted branch, and then a newer version of trunk makes the conflict go away! I only have to choose to address the conflict at the moment I want to return to work on foo.

There's broader implications here, but in practice, it's just that it's simply nicer to have choice.