Splitting a Git Commit
41–50 of 74 posts
Re: Splitting a Git Commit
#42It seems strangely polarizing to refer to the "old and cumbersome" interactive rebase approach in contrast to "the right approach" using `git history` which is a brand new, experimental feature as of Git 2.54 from April 20, 2026, a few months ago. I have split a lot of work with interactive rebasing. I'm excited to try `git history split` and to have learned about it here. But the stylistic flourish makes it seem lik…
I agree, interactive rebasing existed for ages and git history is mainly a user experience improvement over it. This way of framing git history goes way past engagement tricks and erodes the blogger's credibility.
The new `git history` command can take three verbs - fixup, reword and split. While interactive rebasing can do fixup and rewording relatively easily and the `history` variant is a slight improvement, the split sub-subcommand is really _quite_ difficult to do in other Git tooling, including interactive rebase. Before reading on, I would challenge the reader to think about how they might do it.
The answer is that you would rebase back to at least the commit you're splitting, choose 'edit' in the rebase script for that commit (pick the rest), then when the rebase stops there, `git add (-p)` the parts you want, commit, then commit the rest, then `git rebase --continue`. I would guess that maybe 5% of the readers of this paragraph would have guessed that correctly, if I'm being pretty positive.
Patrick wrote the `git history` stuff because tools like JJ and GitButler are pushing UX that makes this type of thing very easy and Git itself is struggling to catch up. Even at a fundamental level, the first versions of history were based on the sequencer code that rebase used but it couldn't do the job properly (messing with the index/workdir), so he rewrote it based on the `git replay` machinery instead (which _itself_ is still somewhat experimental).
Interestingly, it's _still_ not optimized for agents or scripting - `split` specifically needs an interactive terminal like `git add -p` does, so not many agents are good at it. I recently tried it and Claude piped `y\ny\nn` through the command, guessing at the interactive input (y, y, n) needed to stage the hunks.
The point is, interactive rebasing is a horrible solution to this problem, `git history` clearly better, at least for splitting, but really we need non-interactive solutions to problems like this so agents can do them well.
GitButler does this well because we focus specifically on it - our status command gives hunks/files ids and hunk/file movement can happen between commits so splitting is creating an empty commit and then moving the parts over - but it's surprising that nobody else builds tooling for this increasingly common use case.
I think `git history` will slowly get better at this over time, but "interactive rebasing" is a _much_ more error prone and unintuitive way to accomplish this.
Re: Splitting a Git Commit
#43Earlier quoted context omitted.
I think this is harsh criticism. It's because not many people use SO any more. One of SO's selling points was that outdated answers get replaced with the more modern, better ones - and it worked for many, many years.
> One of SO's selling points was that outdated answers get replaced with the more modern (...) I don't think this is description is right. What you describe as "outdated answers" are actually answers to apply up to specific releases. Just because a project launches a release that rolls out a new feature that doesn't render the old answers wrong or stale.
It was introduced in 2.54, which was in April of this year, so less than 4 months ago. Almost nobody can run this command unless they're _really_ on top of things.
Re: Splitting a Git Commit
#44What are people doing to workaround this? I’ve tried to ask LLMs, but the complexity is frankly a bit off putting (I don’t have the suggestions handy)
Re: Splitting a Git Commit
#45That's good to know, I'd usually go about it in a roundabout way: soft reset the commit then git add --patch to stage the hunks to split it into multiple commits.
It's not that roundabout compared to what `git history split` is doing. It's sort of the missing tool in a lot of the rebase discussions (in the Stack Overflow answers). Basically `git history split` is most useful for "split an older commit in this branch", so it's a higher level complex dance of, essentially: - `git rebase -i` - Change the TODO list to `edit` the chosen commit (everything else to `pick`) - At the `…
Re: Splitting a Git Commit
#46`git history` was introduced as an experimental command less than 4 months ago, which means that there are essentially zero OS releases that packages a version that contains it by default. Also, if you're on OSX and run `brew install git`, it will not overwrite the Apple version that is too old to have it.
Git 2.54 was the first release with this subcommand and it is not in Xcode CLT, Debian testing, Ubuntu 26.04 - nothing. It will be "normal" in a year, but it's ridiculous to criticize SO for "old" methods of splitting long before anyone ships with it.
Re: Splitting a Git Commit
#47Earlier quoted context omitted.
I agree, interactive rebasing existed for ages and git history is mainly a user experience improvement over it. This way of framing git history goes way past engagement tricks and erodes the blogger's credibility.
Not sure if this is written by an AI, but I'll engage, because it's a bit misleading. The new `git history` command can take three verbs - fixup, reword and split. While interactive rebasing can do fixup and rewording relatively easily and the `history` variant is a slight improvement, the split sub-subcommand is really _quite_ difficult to do in other Git tooling, including interactive rebase. Before reading on, I w…
If it’s for scripting why not use the lower level ‘git update-index’. Start from the original file and a patch filed, edit the patch, apply it, and then add it the modified file to the index. The patch is the container of changes in my opinion, better have the agent act on that and then apply it instead of working interactively with the work tree.
Re: Splitting a Git Commit
#48I’m doing rebasing a lot these days, especially since I started using gh stack. The main struggle I have with rebasing is for git to recognize that a branch has actually been merged when its commits have changed (e.g., if I forgot to delete the local branch with old commits and come back months later and trying to figure out if it was actually merged or not). My understanding is that this is nicer with jj when you wo…
The common advice is to never have long standing branches for WIP. But if you do, squash it to have a small number of commits, then replay it on top of the default branch. The try to understand why there’s any diff or conflict (refactor, update to the design, code removal, was not merged at all,…). As I squash merge, I always remove the PR branch from the main repo. And I keep it for about a week on my local repo (In case the PR is reverted and I needed my drafting version of it).
Re: Splitting a Git Commit
#49https://github.blog/open-source/git/highlights-from-git-2-54...
And discussion at the time:
Re: Splitting a Git Commit
#50Earlier quoted context omitted.
Not sure if this is written by an AI, but I'll engage, because it's a bit misleading. The new `git history` command can take three verbs - fixup, reword and split. While interactive rebasing can do fixup and rewording relatively easily and the `history` variant is a slight improvement, the split sub-subcommand is really _quite_ difficult to do in other Git tooling, including interactive rebase. Before reading on, I w…
> The point is, interactive rebasing is a horrible solution to this problem, `git history` clearly better, at least for splitting, but really we need non-interactive solutions to problems like this so agents can do them well If it’s for scripting why not use the lower level ‘git update-index’. Start from the original file and a patch filed, edit the patch, apply it, and then add it the modified file to the index. The…
The first is that update-index only works on worktree files, so you need to be actually modifying file contents on disk and then essentially running `hash-object` on them, then `commit-tree`, etc. For an agent, each of these are tool calls and ones that they're not very good at (because nobody really does this manually).
Quick example for clarification. Let's say you want to move half of the changes of a file from one commit to another.
The ideal way would be to run something like:
`git squash : `
Which could load the tree of commit-a into memory, virtually apply the hunk change to it, calculate the new tree, write it out and rebase the commits - thus moving the hunk. This is what tools like GitButler do with `but squash` etc. One command, pretty simple, all in memory and extremely fast.
The "plumbing" path you suggest would be something like:
- (record patch changes you want) - git reset HEAD~3 - (apply patches you want in commit 1) - git update-index - git commit - (apply patches you want in commit 2) - git update-index - git commit - (recreate the commits above that)
You talk about not interacting with the work tree, but `update-index` directly deals with the working directory. It's just not built for operations like this. It's built for Linus interactively building trees from contents on a filesystem.