A drawing of the phrase "Combining Commits" being crushed.

Git Basics: Combining two (or more) commits into just one

Igor Marques da Silva
4 min readOct 4, 2016

--

This post is an extraction of a subsection of this git workflow tutorial (with a few additions). If you are interested in learning more about the workflow used by many teams around the world, check it out!

This post explains one simple way to combine two commits with the power of git™.

I assume you are working on a branch alone to avoid messing around with your teammates' work. Remember: shared branches are usually very hard to maintain.

Let's get to the point!

You have a commit history like this one (older commits on top):

f7f3f6d create file_a class and methods
310154e improve SomeOtherClass code
a5f4a0d update changelog
a412dbb fix typo on file_a

But hey, notice that on commit a412dbb you’re fixing something that you just added on this pull-request (on the first commit, to be exact)… It would be nicer to have both the creation and the fix of file_a on only one commit!

To achieve that, you can use this awesome feature of git: git interactive rebase.

So we need to merge the first commit (f7f3f6d with the last one a412dbb). And that’s when the interactive rebase tools comes in hand.

$ (some_branch) git rebase -i origin/master

The origin/master param is our start point. This basically is telling git: “hey, we want to change the history since the last commit origin/master”, otherwise known as… your branch!

You can also use HEAD~4 as a param, which works like: “hey, we want to change the history since 4 commits behind the current one”. The official docs has more details on this.

After executing the command, this file will show up (probably on the vi/vim editor. Check this cheatsheet if you don’t know how to use it):

pick f7f3f6d create file_a class and methods
pick 310154e improve SomeOtherClass code
pick a5f4a0d update changelog
pick a412dbb fix typo on file_a
# Rebase 710f0f8..a412dbb onto 710f0f8
#
# 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
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Now we just need to follow the instructions written there! We want to combine commits f7f3f6d and a412dbb. So we must reorder the lines to be like this:

pick f7f3f6d create file_a class and methods
pick a412dbb fix typo on file_a
pick 310154e improve SomeOtherClass code
pick a5f4a0d update changelog

And we change the pick label on the a412dbb commit to a fixup (or f), to tell git: “hey, we want to combine this guy with the one above it”:

pick f7f3f6d create file_a class and methods
fixup a412dbb fix typo on file_a
pick 310154e improve SomeOtherClass code
pick a5f4a0d update changelog

Save your file and bang! Here’s your new commit history:

b7c3f33 create file_a class and methods
1b24ae9 improve SomeOtherClass code
d5ffad3 updates changelog

(yeah, the hash of all commits changed due the rewrite of the history).

If you already pushed your branch to remote, remember to use -f next time you push, since you’ve rewritten the your commit history:

$ (some_branch) git push -f origin some_branch

Be warned: pushing with -f is a very dangerous thing. Proceed with caution and always be sure that you’re pushing to the right branch.

And there you go!

Remember: NEVER rewrite the commit history of public branches (like master). This will truly mess your teammates work.

To combine three or more commits into just one, just edit your file to be like this:

pick f7f3f6d this is my first commit
fixup a412dbb this commit will be added to the first one
fixup 310154e and this commit too
fixup a5f4a0d and also this one

All the commits you want to combine into the first one are with the fixup tag.

And you're good to go :)

If you want to simply add a few more changes to your last commit only, it's even easier. Check this post.

Stuff like splitting a commit into different ones and some other crazy ways to change your history are described in the official git documentation.

Happy gitting!

--

--