You can split commits.
Table of contents
git rebase -i
command, it begins your journey into some very important tooling: interactive rebasing.The workflow
This workflow shows you how to split an arbitrary commit, <commit hash>
. It does not matter how far back in your history this commit occurred.
add
a changeset, commit
the changeset, stash
all other changesets, test
the isolated changeset, commit
any fixes required to make the changeset stable and correct, pop
the excluded changesets back onto the working tree.A basic outline
git rebase -i <commit hash>^
change the action for
<commit hash>
from pick to editclose the
git-rebase-todo
editor sessiongit reset HEAD^
iterate until working tree is clean:
git add
git commit
(optionally) isolate and test changeset:
git stash
execute measures of quality/correctness
commit the fixes to any issues identified
git stash pop
git rebase --continue
A more detailed outline
Ensure the defined range includes the commit to split
1. From the command line, execute the interactive rebase script. Since we want to split <commit hash>
, we must ensure it is within the range of the rebase operations. We do that by passing the last commit we want to retain as-is as an argument to the script: git rebase -i <commit hash>^
.This will mean that <commit hash>
's parent lies outside of the range - but crucially, <commit hash>
will not.
<suffixed_commit>^
, the caret symbol (^
) changes the reference to the parent's commit hash. That is, the expression <suffixed commit>^
now refers to the commit that was done before <suffixed commit>
. Visually, this is the commit that appears immediately after or below <suffixed commit>
in the git log
.Use the editor to nominate which commits to split
2. In the git-rebase-todo
file that opens in your editor, mark <commit hash>
(and any other commits you want to split) for editing by replacing the "pick" action with the "edit" action. The rebase script will stop on these commits and await your Git commands.
Close git-rebase-todo
to execute the listed commands
3. Close the git-rebase-todo
file to continue the rebase script's execution.
Use Git operations to modify the commit
4. When the rebase operation stops at <commit hash>
and gives you a command line prompt, use Git operations to split the commit into subcommits.
a. Use git reset HEAD^
to rewind <commit hash>
to its parent. This puts all changes introduced by <commit hash>
back on to the working tree and resets the index (so that there a no staged changes).
HEAD
.b. Use a staging technique (such as git add
) to add the next changeset you want to do a subcommit with to the index.
c. Use a commit technique (such as git commit -m <type: message>
) to commit the changeset.
fix: <message>
commit.d. Use git stash
to temporarily move the uncommitted changes off the working tree. This has the effect of isolating the subcommit from all the other changes that were reset onto the working tree by git reset HEAD^
.
e. Test the current state of the repository against the measures of stability and quality you use. For example, you can see if the code compiles or if a test suite passes.
f. Use git stash pop
to undo git stash
and move all the other changes (the changesets that have not been committed yet) back onto the working tree.
g. Iterate steps b through f (add
through pop
) until the working tree is clean.
h. When the working tree is clean, use git rebase --continue
at the command line to advance the rebase operation to the next "edit" action in the git-rebase-todo
file.
Apply the Git Operations loop to each nominated commit
5. If you marked other commits with "edit", the rebase operation will stop on them after git rebase --continue
; if it does, go to step 4a (git reset HEAD^
). Do until done.
Subscribe to my newsletter
Read articles from Warren Markham directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Warren Markham
Warren Markham
I've worked in an AWS Data Engineer role at Infosys, Australia. Previously, I was a Disability Support Worker. I recently completed a course of study in C and Systems Programming with Holberton School Australia. I'm interested in collaborative workflows and going deeper into TDD, automation and distributed systems.