git rebase -i
# squash all the commits (e.g. in vim with ctrl-v)
git reset HEAD^
git add -p
# interactively pickup the RED hunks
git ci -m RED
The main difference to jj is that the RED commit is created later with git.Jj is not git and is not a git tool, it just (thankfully) uses git as a backend, so you can still carry on with the rest of the world.
In what way is that different from using `git rebase -i` to edit a commit?
There are no modal “sorry rebase failed, best of luck” gotchas. There are no “oops I put the wrong thing in the wrong part of the rebase and now I have to abort and start all over” gotchas.
It’s rebase, but without all the extra work, mental overhead, failure cases, and effort.
You might not think this is that big a deal, but this also means you don’t have to resolve the entire thing in one go. Plenty of times with complicated rebases in git, I’ve not been 100% certain about the path towards resolving it. But jumping around to view various commits when you’re in the rebase-conflict state is painful. In jj you can just switch to an earlier commit, tweak it there, jump to a later commit, see how it looks, etc. It removes 98% of the pain.
It also dovetails nicely with other aspects of jj. Since rebases happen automatically and constantly, they are usually tiny. If there’s a conflict, it’s caught right when you do the thing and not four hours later when that part is no longer fresh in mind. And the op log lets you restore and undo actions atomically, which makes undoing a fuck-up a no-op.
A merge conflict means that some automated tool couldn’t figure it out. But all a merge is is a commit with two parents and an accompanying diff that shows the process of combining them. A merge conflict isn’t really in any way special. It just means whatever algorithm was used couldn’t do it unambiguously without human help.