Subject: Re: [PATCH RFC v3 00/18] Introduce git-history(1) command for easy history editing

From: Phillip Wood <[email-masked]>
Date: Wed, 10 Sep 2025 15:05:20 +0100

On 07/09/2025 07:46, Elijah Newren wrote:
> On Thu, Sep 4, 2025 at 11:43 PM Patrick Steinhardt <[email-masked]> wrote:
>>
>> Hi,
>>
>> over recent months I've been playing around with Jujutsu quite
>> frequently. While I still prefer using Git, there's been a couple
>> features in it that I really like and that I'd like to have in Git, as
>> well.

Fantastic, thanks for working on this

>> A copule of these features relate to history editing. Most importantly,
>> I really dig the following commands:
>>
>>    - jj-abandon(1) to drop a specific commit from your history.
>>
>>    - jj-absorb(1) to take some changes and automatically apply them to
>>      commits in your history that last modified the respective hunks.
>>
>>    - jj-split(1) to split a commit into two.
>>
>>    - jj-new(1) to insert a new commit after or before a specific other
>>      commit.
> 
> Cool, I had been thinking of adding some jj-like functionality as
> well, to git-replay in my case, though I was more interested in fixing
> up the infrastructure to handle replaying merges sanely first.

Interesting, one of the questions I have about this series is whether it 
makes sense to use the sequencer or extend git-replay. I do like the 
idea and name "history" though. I've been using a wrapper around 
git-rebase that I call "git-rewrite" that lets me amend, reword, or drop 
commits and rewrite all the branches that contain the modified commit 
for quite a while now. I find amending the commit directly rather than 
using fixup commits and then squashing much more convenient and it 
avoids the problem of the fixup having conflicts when you try and squash 
it (though not the conflicts caused by amending the commit of course). 
One feature I particularly like, which we might want to add to "git 
history" in the future, is being able to specify a filename, line pair 
instead of a commit name. The script then uses "git diff" to map the 
line number to the file in HEAD and "git blame" to find the relevant 
commit. This makes it easy to start a rewrite directly from my editor 
when I see something that needs fixing up.

If we do want to use the sequencer then I think we need to decide 
exactly what behavior we want from the new command with regard to 
running hooks and copying commit headers and implement that behavior 
rather than just accepting the status quo which is largely a historical 
accident. I would suggest that for commits that we're not modifing we 
should not be running any hooks. For commits that are reworded we should 
be running the "commit-msg" hook and possibly "prepare-commit-msg" as 
well but no others. Where we're amending the commit content or splitting 
a commit then we should be running the "pre-commit" hook as well. 
Currently "git-replay" copies any extra commit headers when it creates a 
new commit whereas "git-rebase" does not. There is some discussion at 
[1] where people were pushing back against copying extra headers by default.

I think it would make sense in the long run to update all the branches 
that contain the modified commit. To do that we can use the sequencer's 
"update-ref" command. To that end I think we should add a new entry 
point to the sequencer that takes a todo list rather than a list of 
commits to pick. That would also allow us to implement the "split" 
command in the sequencer and reuse the infrastructure that already 
exists for rewording commits. The way this series is currently 
implemented makes it hard to extend in the future because it is based 
around cherry-picking commits rather than creating a todo list for the 
sequencer to execute.

Thanks

Phillip

>> Not all of these commands can be ported directly into Git. jj-new(1) for
>> example doesn't really make a ton of sense for us, I'd claim. But some
>> of these commands _do_ make sense.
>>
>> I thus had a look at implementing some of these commands in Git itself,
>> where the result is this patch series. Specifically, the following
>> commands are introduced by this patch series:
>>
>>    - `git history drop` to drop a specific commit. This is basically the
>>      same as jj-abandon(1).
>>
>>    - `git history reorder` to reorder a specific commit before or after
>>      another commit. This is inspired by jj-new(1).
>>
>>    - `git history split` takes a commit and splits it into two. This is
>>      basically the same as jj-split(1).
 >>>> If this is something we want to have I think it'd be just a starting
>> point. There's other commands that I think are quite common and that
>> might make sense to introduce eventually:
>>
>>    - An equivalent to jj-absorb(1) would be awesome to have.
>>
>>    - `git history reword` to change only the commit message of a specific
>>      commit.
>>
>>    - `git history squash` to squash together multiple commits into one.
>>
>> In the end, I'd like us to learn from what people like about Jujutsu and
>> apply those learnings to Git. We won't be able to apply all learnings
>> from Jujutsu, as the workflow is quite different there due to the lack
>> of the index. But other things we certainly can apply to Git directly.
> 
> So, this brings up a question.  Should we have git-rebase &
> git-cherry-pick & git-replay & git-history, or should we consolidate?
> I had envisioned having git-replay consolidate both cherry-pick and
> rebase functionality into one (then got pulled away by combination of
> work reassgniment & multiple life crises hitting at once taking my
> focus away for quite some time).  But now we're going in the other
> direction.  And further along that other direction is another extreme
> -- just having these be top-level commands, e.g. "git reorder", "git
> split", etc.
> 
> In a separate conversation we had (and I hope I'm paraphrasing
> correctly; if not please correct me), you mentioned you wanted
> git-history to be the home of history rewriting, and viewed git-replay
> as just a server side thing (whereas I created git-replay specifically
> as a user-focusing thing and then Christian changed it into a
> server-side thing since that part was complete and enough for his
> purposes).  But if git history is the home of history editing, how far
> does that go?  Do we have a "git history reset"?  "git history
> commit"?  "git history fast-export/fast-import"  "git history
> filter-repo"?  Or is it just the home for certain kinds of history
> rewriting operations?  If so, which ones?
> 
> That all said, I'm a big fan of the idea of incorporating more of jj
> capabilities, and you clearly marked the command as experimental
> (thanks!), which leave us room to adjust later if we don't like this
> path.  So I don't want to serve as a roadblock, I just think it's a
> useful conversation to have...
>