How to Combine Multiple Commits into One in Git

See how to combine two commits into one in Git by using interactive rebase, Git bash, and Vim

In our last tutorial, we showed you how to delete a commit in Git, so it does not appear in the Git history anymore. Here, we will examine a similar approach to merge different small commits into one bigger commit.

There might be some cases where you may want to manipulate the Git history. Clear history makes it easier for your fellow workers to understand what is going on with your code. On the contrary, a messy Git log will leave your colleagues scratching their heads over what you have done and may even lead to frustration and negative feelings and thoughts. So, it is always better to keep a clean and concise Git history that everyone can understand. In this particular case, we will take a look at how to combine two smaller commits into one commit in Git. Perhaps you tried to introduce a new feature, but you only did half of the work in the first commit, and you finished the work in the second one. While you were doing the job, it probably looked like a good idea, but now, when you think about it, it does not make sense anymore, and you wish that you had kept things in one commit. Well, I have good news for you! You can easily combine multiple commits in Git by using the Git command line and vim. In a minute, I will show you how to do it, but now let’s do a quick refreshment on some of the terminology that we are going to use below. Feel free to skip it, if you want, but I would rather keep it here for reference.

Git History

As self-explanatory as it can get, Git history is the history of your commits. An easy way to see a graphical representation of your commits is by running the following command in Git bash:

git log --oneline

This command will provide you with a list of the commits on a given branch starting from newest to oldest.

Interactive Rebase

The interactive rebase is a powerful tool that should be used by people who know what they are doing. Think about it as a deadly weapon that should not be allowed to go to the wrong person. However, the interactive rebase is exactly what we need in this situation. It lets you manipulate Git history in every possible way.

Vim

Vim is the default text editor in Git bash. This tutorial assumes that you are using Vim as a Git bash editor. If for some reason you are not using it, it is the right time to start doing so:

git config --global core.editor "vim"

NB: Vim is a prehistoric tool, a text editor at least as powerful as the rebase method (maybe much more). It is extremely old and unintuitive but it works well in this situation (as well as in many others, given the fact that you know what you are doing). You have been warned.

Combining Commits in Git

After you have checked your Git history with the log command and determined the commits you want to squash (let’s say you have three commits in total and you want to combine your second and third most recent commit)

Open the Git bash and add the following command:

git rebase -i HEAD~3

This will trigger the vim editor and display the last three commits on a given branch.

Pic 1: Interactive rebase in Vim

To combine the commits ending with 283 and 706, press i and then remove “pick” text from the second commit and change it to “s”:

Pic 2: Squash a commit in Vim

This will merge the second commit into the third one to combine the two commits into one. To do the squash, exit visual mode by pressing esc and then type :wq to save and exit Vim.

This will lead you to the final Vim screen, which tells you that the two commits will be combined and gives you the option to modify the text of the commit message. If you are happy with the current message, you can exit the screen by pressing :q

Pic 3: Edit a commit message in Vim

That’s it. You have successfully combined commits 8cac706 and b159283 into one. Do not forget to push the changes with the following command:

git push origin +branch

You need to use force since you have successfully manipulated the git history on your local branch.

PS: You can always cancel the rebase by using the following command in case the rebase goes wrong for some reason:

git rebase --abort

Happy coding!