I'm trying to understand, would jj's first class conflicts solve the issue of having "stacks" of PRs that can easily be updated at any point in the stack? This is one of the features most absent from git, but prevalent in Google's tooling as well as Meta's. The only good known solution I know is graphite.dev
gpm|4 months ago
You can modify any* commit in `jj` regardless of whether it has commits on top of it at any time. Either by another commit into it, or by directly checking out the commit and editing the source tree. If this creates conflicts with commits on top of it `jj` just records those commits as having conflicts/adds conflict markers without interrupting the workflow.
* Commits pushed to remotes are marked immutable so you have to pass an extra flag to say ignore that and modify them anyways. Which you generally wouldn't want to do.
verdverm|4 months ago
How does recording the conflict, but not introducing it (if I'm understanding correctly), ... how does this affect my build/ci workflow?
eddd-ddde|4 months ago
If I amend a commit, all children are rebased automatically.
sfink|4 months ago
Yes, jj very much supports this workflow. It's not a single feature, though:
- `jj absorb` automatically guesses what patches in your stack your changes should go to and puts them there, leaving uncertain ones behind. Combine this with `jj undo`, and you can first try an absorb and then immediately undo it if it gets it wrong. - `jj squash --interactive --into X` (aka `jj squash -i -t X`) is the more controlled option, where you can select the specific files/hunks/lines to amend X with. The auto-rebasing then adjusts the rest of the stack to match. If it creates conflicts, you can either undo, fix them now, or fix them later. - if you want to experiment with reordering your stack (or more generally, reorganizing your DAG), you can do so without it making a bigger mess than is absolutely necessary. That's not just because of undo. If you try to rebase a patch too early and it produces tons of conflicts, you can rebase it back and the conflicts will be gone (assuming you didn't have some in the first place, but if you did you'll be back to the same ones). You can try different places within the stack and see what'll work best. - As an expansion of the above, you can also split off pieces of one diff and insert it or squash it anywhere in the stack (eg `jj split --revision X --insert-after Y` aka `jj split -r X -A Y`, or `jj squash --interactive --from X --into Y` aka `jj squash -i -f X -t Y`). You don't need to be "at" X to rip off pieces and put them elsewhere, you can do it anytime.
In summary, the full answer is "hell yeah!"
Note that this doesn't magically eliminate all problems that arise from collaboration. You can't push your stack somewhere and have other people start working off of it and modifying it while modifying it yourself locally. Or rather, you can, but you'll end up with a mess. Perhaps much less of a mess than eg git, because jj tracks evolving changes and not just commits and so you might be able to have some idea of what's going on once you've pulled the conflicting mutations back into your local repo. But generally speaking, you still have to be disciplined about changing anything that other people can see and possibly depend upon. (jj can help by automatically making such things immutable once you've made them visible to others, but that too can be a bit confusing and require setup specific to your situation.) This comes up a lot in code review, and there are solutions that handle parts of the problem with varying degrees of success, but I've already rambled quite a bit.
1718627440|4 months ago
> `jj absorb`
git absorb exists.