Combining Git commits with squash
Squashing essentially allows you to combine commits together. This is useful for re-packaging commits that are related to eachother in the pursuit of cleaning up history before pushing to an upstream master, or when you’re doing some cleanup on your local development branches.
The basics
Say I have a graph that looks like this. You can see I split off some commits onto a bug fix branch:
I’ll need to get my commits back onto mainline, and I can use merge or rebase to do that; however, with either solution, all my local branch commits would be preserved. Usually, preserving commits like this is a good idea, but let’s say you made a typo somewhere and had to create another commit to fix the spelling error. Or you have a bunch of local commits related to a bug fix, but you’d really rather just have all of those related commits under one roof. Enter squashing.
Squashing allows you to rewrite history and combine together commits.
In practice: the actual commands
Now that you know what squash is, let’s take a look the actual commands. Again, we’ll say my starting point is my bug fix branch with 3 commits.
It would be nice if I didn’t have to preserve these extraneous commits as separate entities since they are all related to a bug fix. I’d rather combine them together into one clean commit.
With my bug fix branch checked out, I’ll start by running the interactive rebase command with HEAD~3. This lets Git know I want to operate on the last three commits back from HEAD.
Git will open up your default terminal text editor (most likely vim) and present you with a list of commits:
There are a couple options here, but we’ll go ahead and mark commits we’d like to meld with it’s successor by changing pick to squash. (If you’re using VIM, type i to enter insert mode)
Press ESC then type :wq to save and exit the file (if you are using VIM)
At this point Git will pop up another dialog where you can rename the commit message of the new, larger squashed commit:
Simply saving this file without making changes will result in a single commit with a commit message that is a concatination of all 3 messages. If you’d rather rename your new commit entirely, comment out each commit’s message, and write you’re own. Once you’ve done, save and exit:
That’s it. You can either merge or rebase your branch back to mainline.