In this post, we'll see how to combine multiple commits into a single one using a powerful git feature called interactive rebase.
Table of Contents
1 - Why combine commits?
Before getting into the explanation itself, I think it's important to look at the reasons why combining multiple commits into one can matter.
The main reason is to organize or clean up our workspace.
But what do I mean by that? When you do a pull request and your teammates review your code, it's common for them to have opinions or suggestions for changes.
In most scenarios these changes are minimal — they can be a lot or a few, it doesn't matter much — but in the end, they're just some tweaks. For example, naming conventions for variables, methods, or maybe some algorithm that could be improved.
Also, those comments aren't usually made all at once. When the person reviewing your already modified code finds something new, you might end up with a commit structure like this:
This happens to all of us, there's nothing to be ashamed of — in fact, it's much better if it happens in the pull request instead of running into “bad code” while doing something else.
As we know, when merging, all commits are applied, so the history of our main
branch will also contain the infamous "pr comment" commits. Ideally, we should "clean" those commits, so they don't get in the way, for example, when viewing the history of a file. Our structure should look like this:
This way, when we merge from the pull request, we’ll only see the combined commit in the history.
2 - Combine multiple commits with git CLI
To combine multiple commits, you need to know either the number of commits you want to combine or the hash.
What we want here is to combine all the commits made on July 11th.
2.1 - Interactive rebase in git
So, we'll go to the command line and execute one of these two commands:
git rebase -i [your hash]
or git rebase -i HEAD~(number of commits to review)
; In our case, we run:
git rebase -i HEAD~4
Note: if you opt to use the commit hash, make sure you choose the commit prior to the one that would be the “initial” one. In my case, it would be the hash for the commit from October 16, 2020.
2.2 - Squash multiple commits
Once the command is run, a text editor will open, where you'll first see the commits, listed in chronological order from oldest to newest.
After that, you’ll see instructions on how to use the file.
pick 39b2d22 Commit task1
pick aca2254 pr notes
pick 0b0c7dc pr notes
pick 343420f pr notes
# Rebase 35ffbb6..343420f onto 343420f (4 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# 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
As you can see, it explains the commands. The most common will be pick (p)
, which means that commit will stay in the history, or squash (s)
, which means that commit will be merged with the previous one.
So, we change our file so it looks like this:
pick 39b2d22 Commit task1
s aca2254 pr notes
s 0b0c7dc pr notes
s 343420f pr notes
As you can see, we combined all the commits with "pr notes" into "commit task 1"
Once you close the text editor, the changes will take effect, and you can run git push
.
3 - Combine commits using GitHub Desktop
You can also do this using the GitHub Desktop application. Just go to your branch and review the history.
Select the commits you want to "make disappear" and drag them onto the initial commit:
A small window will pop up where you can edit the commit and its message, and it will include the messages from all the commits you’re squashing.
When you confirm, you’ll see that all the commits are combined into a single one:
Conclusion
In this post, we've covered:
- The importance of combining commits
- How to combine commits using the command line interface
- How to combine commits using GitHub Desktop
If there is any problem you can add a comment bellow or contact me in the website's contact form