Join us on Facebook!
— Written by Triangles on August 09, 2021 • updated on September 06, 2021 • ID 92 —
A quick and easy way powered by git rebase.
Imagine you are working with multiple files in a Git-managed project. At some point you create a commit that include, say, changes to files
c.txt. Then, hours and many commits later, you realize that changes done to
b.txt should not be part of that commit. Maybe you want to move the changes done to
b.txt to another commit, in order to make your history clearer. In this quick tutorial I want to show you how to split a commit into multiple parts the easy way.
The first thing to do is to look at your commits history and pick a commit older than the one you want to split. Say for example that this is your history (as shown with
git log --oneline):
527247a (HEAD -> master) Add support for videos 06be701 Optimize memory allocation 85a90cf New rendering engine <--- the commit you want to split ddb5c99 Update graphics af1bcb2 Update documentation ...
85a90cf New rendering engine is the one you want to split. Since commit
af1bcb2 Update documentation is older, copy its hash.
I'm going to use the interactive rebase for this step. Invoke it with
git rebase -i <your-previously-copied-hash>
git rebase -i af1bcb2
This command will open up your text editor of choice with a list of all the commits starting from (but excluding) the one you passed in. Note that it might be confusing at first, since they are displayed in a reverse order, where the older commit is on top. I've added
--- older commit and
--- newer commit in the snippet below to make it clear, you won't find those notes in the editor:
pick ddb5c99 Update graphics --- older commit pick 85a90cf New rendering engine pick 06be701 Optimize memory allocation pick 527247a Add support for videos --- newer commit [... notes here ...]
[... notes here ...] part you will find instructions on what you can do in this page: we need the
edit command to manipulate our commit. Find the commit you want to split in the list and change the
pick word into
e in short). Your commit list in the editor should now look like this:
pick ddb5c99 Update graphics edit 85a90cf New rendering engine pick 06be701 Optimize memory allocation pick 527247a Add support for videos [... notes here ...]
Save the file and exit the editor. The rebase procedure has begun.
You are now editing commit
85a90cf New rendering engine. Let's undo it:
git reset HEAD~1
Now all the changes done in that commit are unstaged and need to be committed again. This is the step where you create new smaller commits, or in other words where you split the original one. Commit the pieces individually in the usual way (
git commit ...), producing as many commits as you need.
When you are done with your surgery, invoke
git rebase --continue
to conclude the rebase. Now your history contains new, more granular commits. You can start over again instead with
git rebase --abort in case something goes wrong.
Keep in mind that now you have changed your local commit history, so it might require a force push to remote. Be careful when doing that on branches other people are working on.