Re: [PATCH RFC 00/11] Introduce git-history(1) command for easy history editing
From: Elijah Newren <hidden>
Date: 2025-12-20 16:51:36
On Fri, Dec 19, 2025 at 8:30 AM Elijah Newren [off-list ref] wrote:
On Fri, Dec 19, 2025 at 4:22 AM Patrick Steinhardt [off-list ref] wrote:quoted
[...]quoted
Okay, so the majority of folks here seem to favor rewriting all dependent branches, which is also the default that JJ uses here, and git-replay(1) does it, too. There is one major difference between git-replay(1) and git-history(1) though: the former works with revision ranges, whereas the latter does not. By using revision ranges we avoid the problem I have mentioned in a different branch of this discussion, which is that we have no easy way to figure out which branches we'd have to touch in the first place. This is because we simply walk the revision range there and then look at which of our references point into that range. That's simple enough. But in our case we're not working with ranges, we are working with a singular commit.I don't understand the distinction at all. `git replay edit` also took a single commit, and then implemented the obvious (and jj-like) behavior of rewriting all branches that descended from that commit.quoted
In my head this meant that we'd have to basically do a revision walk that starts from all of our branches so that we can figure out which of them would eventually reach the commit that we are about to rewrite.Yes, and it's only a few lines of code, as I showed earlier.quoted
And that of course doesn't scale.That's quite an assumption about scaling; I don't believe it. Under what conditions would this be slow enough for users to notice and be bothered? commit-graphs not enabled + weird local clone with thousands of local branches? Also, isn't jj specifically designed for large repositories and with scaling in mind, and yet this is their default behavior? More importantly, this is being used to justify a large principle of least astonishment violation (disconnecting branches with shared history), so we'd not only need to show that walking all branches was slower enough for users to notice, but slower enough that the negative user performance experience offsets the negative user experience from the astonishing behavior. Typically, spending extra cycles to provide users with good warnings/errors is a good use of time, especially when it'll take them far longer to discover and recover from negative surprises.
A quick clarification in case I'm misunderstood above: When I talk about rewriting branches descended from the commit, I am specifically talking about refs/heads/*, not refs/remotes/origin/* or refs/tags/* or anything else. Because: * I suspect we'll soon implement an "immutable branches" concept, so that e.g. a request to modify a commit in the history of "main" would result in an error (by default). This leads to the idea that we're just rewriting the user's local stuff they have on top of the immutable history, i.e. their local branches. * refs/tags/* are designed to be immutable, obviously. In fact, we might want to automatically include tags in the set of "immutable branches" by default. * refs/remotes/* are designed to match what the corresponding remote had, not to be independently rewritten. We'd really mess people up if we changed that. * The fact that users created local branches means they are marking those parts of history as a relevant area of interest * While it could be that some of refs/remotes/origin/* have shared history with whatever commit is being reworded/split/edited, so too could branches that were never pushed. I think focusing on the branches of interest to the user (i.e. their local branches) makes sense.