On Tuesday, 19 August 2025 12:56:07 CEST Patrick Steinhardt wrote: > It is quite a common use case that one wants to split up one commit into > multiple commits by moving parts of the changes of the original commit > out of it into a separate commit. This is quite an involved operation > though: > > 1. Identify the commit in question that is to be dropped. > > 2. Perform an interactive rebase on top of that commit's parent. > > 3. Modify the instruction sheet to "edit" the commit that is to be > split up. > > 4. Drop the commit via "git reset HEAD~". > > 5. Stage changes that should go into the first commit and commit it. > > 6. Stage changes that should go into the second commit and commit it. > > 7. Finalize the rebase. > > This is quite complex, and overall I would claim that most people who > are not experts in Git would struggle with this flow. > > Introduce a new "split" subcommand for git-history(1) to make this way > easier. All the user needs to do is to say `git history split $COMMIT`. > From hereon, Git asks the user which parts of the commit shall be moved > out into a separate commit and, once done, asks the user for the commit > message. Git then creates that split-out commit and applies the original > commit on top of it. > > Signed-off-by: Patrick Steinhardt <ps@xxxxxx> > --- > Documentation/git-history.adoc | 59 ++++++++ > builtin/history.c | 245 +++++++++++++++++++++++++++++++++ > t/meson.build | 1 + > t/t3452-history-split.sh | 304 ++++++++++++++++++++++++++++++++++++++ +++ > 4 files changed, 609 insertions(+) > > diff --git a/Documentation/git-history.adoc b/Documentation/git-history.adoc > index 6e8b4e1326..f0f1f2a093 100644 > --- a/Documentation/git-history.adoc > +++ b/Documentation/git-history.adoc > @@ -10,6 +10,7 @@ SYNOPSIS > [synopsis] > git history drop [<options>] <revision> > git history reorder [<options>] <revision> --(before|after)=<revision> > +git history split [<options>] <revision> [--] [<pathspec>...] I just realized that there are no other <options> available for the first two commands! So maybe simplify the synopsis for the time being. The --message is specific to split, so maybe also cite is specifically here. I > > DESCRIPTION > ----------- > @@ -47,6 +48,26 @@ reorder <revision> (--before=<revision>|-- after=<revision>):: > commit. The commits must be related to one another and must be > reachable from the current `HEAD` commit. > > +split <revision> [--message=<message>] [--] [<pathspec>...]:: missing backticks. Also the order of options and <commit> are different from the general synopsis. Is this order allowed? > + Interactively split up the commit into two commits by choosing You can use the placeholder in this sentence: "Interactively split up <commit>..." > + hunks introduced by it that will be moved into the new split-out > + commit. These hunks will then be written into a new commit that > + becomes the parent of the previous commit. The original commit > + stays intact, except that its parent will be the newly split-out > + commit. > ++ > +The commit message of the new commit will be asked for by launching the > +configured editor. Authorship of the commit will be the same as for the > +original commit. > ++ I guess this only happens if --message is not passed? > +If passed, _<pathspec>_ can be used to limit which changes shall be split out > +of the original commit. Files not matching any of the pathspecs will remain > +part of the original commit. For more details about the _<pathspec>_ syntax, > +see the 'pathspec' entry. You may have meant: + For more details, see the 'pathspec' entry in linkgit:gitglossary[7]. > ++ > +It is invalid to select either all or no hunks, as that would lead to > +one of the commits becoming empty. > + > EXAMPLES > -------- > > @@ -88,6 +109,44 @@ f44a46e third > bf7438d first > ---------- > > +* Split a commit. > ++ > +---------- > +$ git log --stat --oneline > +3f81232 (HEAD -> main) original > + bar | 1 + > + foo | 1 + > + 2 files changed, 2 insertions(+) > + > +$ git history split HEAD --message="split-out commit" > +diff --git a/bar b/bar > +new file mode 100644 > +index 0000000..5716ca5 > +--- /dev/null > ++++ b/bar > +@@ -0,0 +1 @@ > ++bar > +(1/1) Stage addition [y,n,q,a,d,e,p,?]? y > + > +diff --git a/foo b/foo > +new file mode 100644 > +index 0000000..257cc56 > +--- /dev/null > ++++ b/foo > +@@ -0,0 +1 @@ > ++foo > +(1/1) Stage addition [y,n,q,a,d,e,p,?]? n > + > +$ git log --stat --oneline > +7cebe64 (HEAD -> main) original > + foo | 1 + > + 1 file changed, 1 insertion(+) > +d1582f3 split-out commit > + bar | 1 + > + 1 file changed, 1 insertion(+) > +---------- > + > + > CONFIGURATION > -------------