Re: [PATCH RFC 00/11] Introduce git-history(1) command for easy history editing
On Fri, Dec 19, 2025 at 8:30 AM Elijah Newren <newren@gmail.com> wrote:
Show 48 quoted lines
>
> On Fri, Dec 19, 2025 at 4:22 AM Patrick Steinhardt <ps@pks.im> wrote:
> >
> [...]
> > 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.
>
> > 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.
>
> > 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.