I think this is generally only useful, if these branches don't need any other change for updating the ancestor. When they need than you need to work on the branch anyway and rebase other commits or add new ones on top, so you gain nothing compared to "rebase --onto" for each branch separately.
If you don't have anything to update then that would be somewhat pointless to me. You can also just rebase them, when you start working on the branch again or want to merge them.
--
For me branches also represent features, that should have clear boundaries, so when I work on one feature and that means, I need to rebase another one on top instead of being able to just merge them later, this indicates a spaghetti codebase where the interfaces between features are not properly defined and things depend on internals of other things.
>For me branches also represent features, that should have clear boundaries
I try to do this too but I often end up in situations where I have multiple incomplete (in testing, not merged) features with outstanding patches. Instead of one branch per topic, I end up with one branch for a bunch of related stuff. I then rebase and pause at the feature boundaries to do more testing. Sometimes, if I find myself doing this a lot, I will use the `exec` feature of `git rebase` to automate my testing.
I think rewriting all related branches can cause problems. It would be really weird to do interactively for one thing. The other problem is that you may have unrelated topic branches broken by such a change. If you have a broken patch X that reveals problem Y on branch Z1, but you are working on fixing that on Z2, you may lose your ability to reproduce the Z1 issue if X is fixed on every branch. What if you get conflicts on all those branches? What does this do to the reflog? Yikes! It seems more dangerous than git itself.
These complaints are very niche of course, but the problem of rewriting many branches at once is also very niche. It can cause more problems than it solves.
That sounds real painful and confusing. You could end up with a bunch of conflicts in separate commits, on multiple branches, none of which you actually wanted to modify in the first place.
Someone just told me that if you rewrite a commit that is an ancestor of multiple branches, it will (or can) automatically rewrite all the branches.
What does it even mean to not resolve conflicts? Your branch code and/or history is broken until you come around and fix it? If so, forcing you to fix it immediately is better. Aside from the practical implications of deferring conflict resolution, I just can't think of a reason I would do it in the first place. If a branch can't be rebased with zero work, and I don't have time to do that work, I just don't do the rebase.
Sure, my point is just that if you don’t want history re-written, you just don’t re-write it. If you have multiple descendant branches and for some reason you don’t want the children to move as well, you can move them back. It’s almost the opposite of what the article describes; instead of needing to choose to move children, children move automatically and you move ones you don’t want to back. I’ve never wanted to do this but if it happened it would be easy enough to fix.
It looks like this: when a git rebase would pause the rebase to make your resolve a conflict, jj keeps going. When the rebase finishes, if there are any conflicts, they’re displayed in the log with ?? after their ID. jj won’t let you push a branch with conflicts until the conflict is resolved. You can fix the conflict by either editing that commit directly, or my preferred way, which is to make a new change on top and then squash the resolution back in after you read it over.
So there’s a few thins about why this is useful: because children are also rebased, you can see immediately how much work, if any, you have to do. I have an alias to rebase all open branches on top of trunk, and will often pull trunk, run it, and see if I have any work to do to update them. “Oh, only one of my three branches needs work, I’ll work on the two that are fine first” can happen, and that third can just sit there. Or, as I said before, I could move it back on top of its old base, and the conflict disappears. Or, say I suspected none of them conflict, but all three do, and I don’t want to do it at all right this moment, I’ll just jj undo and they’re all unconflicted and back in place.
(sorry about the formatting here. I guess you'll have to copy & paste it to read it)
What I'm saying is that if I want to fix something in D, I do `jj new D` to create a new commit on top of D. Then I make the fix, run tests, etc., and then I run `jj squash` to amend the changes into D. The descendant commits (E through J) then get automatically rebased and the feature bookmarks/branches get updated.
I didn't follow what you about it other changes needed for updating the ancestor. Can you explain in the context of this example?
So what I am saying is that after you created D', it is true, that you need to run `rebase --onto` in git, while it is automatic in jj. But I think updating feature2 and feature3 is only really necessary to do now, when you want to change something in G-J also. If you don't and it wouldn't cause merge conflicts at all (logical and physical) then you could also just do this when you work on top of H or J the next time, so it wouldn't actually cause any more work in git compared to JJ.
--
The other thing I am saying is that I don't really let features depend on each other, I let them specify the API between them first and then develop them independently. Otherwise it is easy to violate boundaries. So the ideal is that any of G,H and I,J works with D,E,F and vice versa. Of course that is tangential and it doesn't always work that way.
If you don't have anything to update then that would be somewhat pointless to me. You can also just rebase them, when you start working on the branch again or want to merge them.
--
For me branches also represent features, that should have clear boundaries, so when I work on one feature and that means, I need to rebase another one on top instead of being able to just merge them later, this indicates a spaghetti codebase where the interfaces between features are not properly defined and things depend on internals of other things.