1. We're rewriting some commits. Let's say a chain of commits A through G. We want to make some change to commits A and D.
2. As we're editing commit D, we realized that we need to make some changes to B to match the updated A.
3. Also while editing D we realized that we want to take a look at the state in A to see how something worked there.
With jj, here's what I would do:
1. Run `jj new A`, make the changes, then `jj squash` to squash the changes in to A and propagate them through the chain.
2. Run `jj new D` to make changes. We now notice that we wanted some changes to go into B. We can make the changes in the working copy and run `jj squash --into B -i` to interactively select the changes to squash into B.
3. Run `jj new A` to create a new working-copy commit on top of A, look around in your IDE or whatever, then run `jj edit <old commit on top of D>`. Then run `jj squash` to squash the remaining changes in the working copy into D.
I think you know the steps to do with Git so I won't bother writing them down. I find them less intuitive anyway.
2. Edit changes for D. Also edit changes for B. Interactively `git add` changes for B. `git commit --fixup=B`.
3. Finish changes for D, then call git commit --fixup=D
Before push I run `git rebase --autosquash`, optionally `git rebase --exec='make check'` to rerun all the tests on the changed commits.
Where is that "much harder"?
A few months back I had to sanitize the commit history of a repo that needed certain files removed from the entire history. I could have read the manpage for `git filter-branch`, but in jj editing commits is just a normal, sane part of your workflow. It was a blindingly obvious one-liner that just used all the commands I use every day already.
Even better, it was fast. Because “edit the contents of a bunch of commits” is a first-class operation in jj, there’s no need to repeatedly check out and re-commit. Everything can be done directly against the backing repository.
I don't consider `commit --fixup` to be some arcane workaround, that is basically the default to record a change to some older commit.
Editing commits is also a normal, sane part of my workflow, what else is a version control system supposed to do? I consider modifying every commit in a repo not to be that frequent, but nice if JJ supports that easily. Do you want to educate us of the command?
Git also does certain modifications entirely in memory, but when I edit some file obviously my editor needs to access it. Also I want to rerun the tests on some modified commit anyway, so to me checking it out is not some extra cost.