Like it!

Join us on Facebook!

Like it!

How to split a commit into smaller ones in Git

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 a.txt, b.txt and 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.

Step 1: choose a starting point

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
...

and commit 85a90cf New rendering engine is the one you want to split. Since commit af1bcb2 Update documentation is older, copy its hash.

Step 2: run the interactive rebase

I'm going to use the interactive rebase for this step. Invoke it with

git rebase -i <your-previously-copied-hash>

for example

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 ...]

In the [... 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 edit (or 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.

Step 3: reset the current state

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.

Step 4: finish the rebase operation

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.

Sources

Git documentation — 7.6 Git Tools - Rewriting History
Git documentation — git-reset
Scornful — Break a previous commit into multiple commits

comments
franck on November 21, 2022 at 00:18
You can select the parent commit with git rebase -i 85a90cf^
Joel on April 08, 2023 at 19:39
Excellent tutorial. Might I add that it's a good first step to make a backup branch before doing the rebase. That way if you mess up during the rebase, you can just switch to that branch, delete the main branch, then rename the backup branch "main".