3 ms·
you think you do, but you don't; jj edit is much, much better than an edit step in a rebase - it essentially keeps rebasing while you're editing, so you can alw
by baq 1y ago
you think you do, but you don't; jj edit is much, much better than an edit step in a rebase - it essentially keeps rebasing while you're editing, so you can always see which changes get conflicts, then you are free to resolve them, or not, at your convenience.
- adastra22 1y agoSo you get all merge conflicts at once? How is that better?
- baq 1y agoit's exponentially better because you don't need to resolve them until you're ready. conflicts are committed to the local repo like everything else, commits with conflicts are noisily warned about and you can fix them whenever instead of having no other option than immediately.
- adastra22 1y agoHow does your repo work with conflicts? How does it compile?
- baq 1y agoThe edited commit, assuming it doesn’t have conflicts with predecessors, builds just fine. Successor commits with conflicts that you just introduced predictably don’t - but you aren’t editing them, so it isn’t a problem. In fact, that’s exactly why this feature is so compelling.
- adastra22 1y agoSorry if I’m being dense, but I still don’t get how this is any different. If I interactive rebase and stop to edit a commit, isn’t that the same thing?
- steveklabnik 1y agoYou have to finish the rebase before git will let you move in to other work. jj will not. With git you can stop in the middle to make changes, but you must continue until the rebase is done.
- adastra22 1y agoOk. There are simple workarounds. I git rebase —quit and then make a branch for this saved rebase progress to return to later. I then restart the rebase from the corresponding commit. It would be much nicer if this was all wrapped up a simple command. There is value here, but I think it is more like “add a new command consisting of 50-100 lines of code” not “write an entirely new VCS.”
- steveklabnik 1y agoOne little thing here, one little thing there, it all adds up. The jj model is more orthogonal, and so ends up being easier, which also translates to more power.
- aseipp 1y agoYou have this commit graph B --> X --> Y (main) --> Z --> @ \ --> G --> H B is a base; yesterday the name "main" pointed to it, and today "main" points to Y. Z is a commit you wrote that you haven't published yet. "@" means "Working copy", which is a way of saying "what your filesystem looks like." So, at this time, you see the changes from B, X, Y, Z, but not G or H. You want to rebase G --> H from B to Y. But unfortunately, G conflicts with X. H does not conflict with anything. When you run this rebase in Git, you will actually have to immediately fix the conflict between G and X in order for the rebase to continue. If you do not solve it right then, the entire rebase fails. Git's rebase is actually an algorithm represented by a state machine; you must solve the conflict to proceed from "conflicted state" and `git rebase --continue` the rebase algorithm. (If you imagine what you would need to do to actually implement 'git rebase' as it works today in your own code, this state machine model makes immediate sense.) In Jujutsu, rebase is a non-stop operation and it always succeeds. There is no state machine. It will update the commit graph to look like this: B --> X --> Y (main) --> Z --> @ \ --> G --> H C C Now G and H are marked as "conflicted". If any commit is marked as conflicted, then all (transitive) children are marked as conflicted, too. If you "switch over" to working on G, then you can solve the conflict and commit the solution. That will solve the conflict in G, and also H as well. But you don't have to do anything. In the above graph, G and H are conflicted, but because they are not a parent of `@`, then it does not matter. They exist in a parallel universe that does not influence your own. You can keep compiling code as usual. If you "switched over" to G, then the conflict is "materialized" in your working copy (filesystem) by putting conflict markers in the files, and so you have to solve it to keep compiling. In short, Jujutsu separates conflict computation (do patches X,Y have a conflict?) from conflict materialization (make the conflict appear with markers in a file), and materialization of conflicts is "lazy" -- it only happens if a conflict exists transitively in the history of your working copy. Resolution is then done at your leisure. A more brainiac way of thinking about it is that Jujutsu is a tool for manipulating _commit graphs_, and that is a purely computational notion; adding edges, removing edges, etc are all just basic algorithms. The graph's nodes contain "content" and states like "conflicts" are just defined as a relationship C(X,Y) on nodes in the graph. But all of this is "purely computational." Imagine implementing Jujutsu's rebase command; it is just a trivial reparenting of some graph nodes, something an amateur programmer could do. Calculating the relationship `C` is a bit more involved, but not complete black magic. But none of this involves "reading files from disk" or whatever. The side effect of "update the files on your filesystem to look like state XYZ in the graph" is just that: a side effect that the tool does when it is needed. Git, in contrast, only works through "side effects" in that it tends to only operate on the working copy, and never the "holistic commit graph". And so Jujutsu works at a higher, more "pure" level. ----- Fun fact: in some cases, you do not actually have to "switch over" to G in order to solve this conflict, either. It is actually possible to craft a "solution" to the conflict in G while on top of Z. Then you can do `jj squash --from @ --into G` and you can "teleport" the resolution into the conflicted commit, solving both G and H, without ever making it appear in the working copy. This happens in cases like "G modified a file named readme.txt that was deleted by commit X"; all you have to do is "re-delete" the file inside commit G and it is trivially solved. This is something that is, quite literally, impossible to do in Git.
- ec109685 1y agoTo the sibling comment that is too deep to reply to, this covers why delayed conflict resolution is advantageous: https://news.ycombinator.com/item?id=45084835 https://news.ycombinator.com/item?id=45084835 It’s for other branches that hang off the commit that introduced the conflicts.
- 8n4vidtmkvmk 1y agoJj edit isn't even the jj way of doing things. Should be jj new. Unless you have changes stacked after then you'd do jj new -A. And squish when you're done
- BeetleB 1y agoAs a relatively new jj user, I'm curious. Why is the jj new -A + squash better than just a jj edit?
- baq 1y agoSeparation of concerns and performance; when you edit, the commit in the middle of the branch is your working copy and you’ll update the whole branch unnecessarily many times vs just once when you’re on a logical checkpoint.
- adastra22 1y agoNot everyone works by “logical checkpoint” commit strategy. I myself want my tree clean and commits being atomic state transitions. Otherwise git bisect (which I rely on) would break. A lot of the jj strategies in this thread are a bit more cowboy, and I’m surprised.
- steveklabnik 1y agoThe key is to be cowboy until you’re happy with things, and then get clean, just like with git. It’s way easier to slice and dice commits with jj and so you can be sloppy at first and it’s easy to turn beautiful afterward.
- adastra22 1y agoThat’s not how I use git, at all. I have a messy workspace with a lot of things going on simultaneously, and only selectively stage when something crosses the finish line. Sounds very difficult to do this in jj.
- 1718627440 1y agoYou can use all the git commands while doing a rebase. When you want to work on an older commit for a longer time and don't want to stay in a rebase, you just check it out and work normally, when you are done and want to propagate your changes, then you do a single rebase.
- baq 1y agoI’m reminded of the Dropbox comment. You can do anything with a Turing machine. That you can isn’t the point. The point is the tool does all the things you can automatically and correctly so you don’t have to. There’s no ’just do this or that during rebase, or outside of it’. There’s only ‘it rebased everything correctly without a single thought, nice’.
- 1718627440 1y agoSSH is definitely easier than Dropbox :-). Yes, and my point is that having a rebase and edit everything isn't too different from first modifying everything and then doing an automatic rebase.