Splitting a Commit in Git
In this blog post, we will learn how to split a commit in Git.
Step 1: Clone this repo on your local machine.
git clone firstname.lastname@example.org:pawanpoudel/split_dudeism.git
split_dudeism directory and
git log it.
cd split_dudeism git log --oneline
923c105 Go ahead, read me... 4ea45e4 Split me. I am too big... a258b8e Are you going to a lebowski fest? e61add7 Dudeism - this is where it all starts
Step 3: Let’s split the second commit from top into three. We will give that commit a name first.
git branch split_target 4ea45e4
Step 4: Rebase interactively with
split_target‘s immediate parent as the base commit.
git rebase -i split_target~
We are using the
~(tilde) here to get to
split_target’s parent. You might have seen the
^(caret) being used to get to a parent in other examples. There is a subtle difference between these two. I think
~is a better choice for our example. Plus if you are using zsh as your shell, you don’t need to escape
There should only be two commits in your interactive rebase window.
pick 4ea45e4 Split me. I am too big... pick 923c105 Go ahead, read me... # Rebase a258b8e..923c105 onto a258b8e # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell ...
Step 5: Replace the word
edit for commit
4ea45e4. After that save the file and exit.
edit 4ea45e4 Split me. I am too big... pick 923c105 Go ahead, read me...
If you are using Vim, you can save and exit by first hitting the
Esckey to switch to the command mode. Once you are in command mode, type
:xand then hit the
Step 6: The commit we are splitting adds three files to the repo: the_dude.md, walter.md and donny.md. Let’s make the first commit we are about to split to just about The Dude. For that, we need to first remove the other two files (walter.md and donny.md). We can easily do that by resetting those two files to the previous commit which doesn’t include them.
git reset HEAD~ walter.md donny.md
At this point,
git status should show that walter.md and donny.md have been deleted from the staging area:
git status rebase in progress; onto a258b8e You are currently editing a commit while rebasing branch 'master' on 'a258b8e'. (use "git commit --amend" to amend the current commit) (use "git rebase --continue" once you are satisfied with your changes) Changes to be committed: (use "git reset HEAD <file>..." to unstage) deleted: donny.md deleted: walter.md Untracked files: (use "git add <file>..." to include in what will be committed) donny.md walter.md
Step 7: Now we can ammend the original commit to include only the_dude.md file.
git commit --amend -m "The dude abides"
Step 8: Although the other two files (walter.md and donny.md) were removed from the staging area, they are not removed from filesystem. We can add them back to the staging area one at a time and create separate commits.
git add walter.md git commit -m "You are entering a world of pain"
git add donny.md git commit -m "Phone's ringing, Dude"
Step 9: Now that we have split the original commit into three separate commits, we need to tell Git to finish rebasing.
git rebase --continue
The Git history for
split_dudeism repo should have total of six commits now.
git log --oneline 575f98c Go ahead, read me... 4eee259 Phone's ringing, Dude f4db974 You are entering a world of pain ad8533b The dude abides a258b8e Are you going to a lebowski fest? e61add7 Dudeism - this is where it all starts
Step 10: Finally let’s clean up by deleting the
git branch -D split_target
And we are done!!