Git Squash Commit With Git Rebase

Tharun Kumar Sekar
Analytics Vidhya
Published in
5 min readMay 20, 2020

When submitting a pull request to merge your code with Master/Develop, it’s better you squash your commits. Some applications that interact with git repos will provide a user interface for squashing. But let’s take the fun route — the terminal way.

There are multiple ways to do a git squash. One - do it locally in your system and then push it to remote. The other way is having a copy of all your changes in remote before doing a rebase so you have a copy of your changes in remote in case if something goes wrong.

Lets look at the safer way first. Make sure your branch is up to date with the remote server. Now do git log --pretty=oneline to understand the commits that happened in your branch.

* c88bc5 Implement search inputs for user
* 8f4917 Enriched plots for better understanding
* 59c01d Add pyplot for better analysis
* ba6f1f Add listing feature to quality checks
* 9f2adb Add feature to pipeline
* f796c1 Initial commit

The last 6 commits would look much better if they were wrapped up together, so let’s do that through interactive rebasing.

To interactively rebase commits, you can follow the below format and enter your command via the command line.

git rebase -i HEAD~<n> (n is the number of commits you want to squash)git rebase -i HEAD~6 (This will roll up all 6 commits in the current branch)

or

git rebase -i <sha code> (sha code of the commit until which you want to squash)git rebase -i f796c1 (sha code of the initial commit)

The -i flag is to indicate that this rebase process will be an interactive session.

Once you enter the above command, this is what you will see.

pick f796c1 Initial commit
pick 9f2adb Add feature to pipeline
pick ba6f1f Add listing feature to quality checks
pick 59c01d Add pyplot for better analysis
pick 8f4917 Enriched plots for better understanding
pick c88bc5 Implement search inputs for user
# Rebase 8db7e8b..fa20af3 onto 8db7e8b
#
# 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

We see the 6 last commits, from older to newer. See the comments below the list of commits? Good job explaining, git! pick is the default action. In this case, it would reapply the commit as is, no changes in the contents or messages. Saving this file would make no changes to the repository.

We are interested only in the below actions.

  • squash ( s for short), which melds the commit into the previous one (the one in the line before)
  • fixup ( f for short), which acts like “squash”, but discards the commit message

Let’s say we want to squash all our commits, because they belong to the same logical changeset. We’ll preserve the initial commit and squash all the subsequent commits into the previous one. We have to change pick to squash in all the commits except the first one.

pick f796c1 Initial commit
squash 9f2adb Add feature to pipeline
squash ba6f1f Add listing feature to quality checks
squash 59c01d Add pyplot for better analysis
squash 8f4917 Enriched plots for better understanding
squash c88bc5 Implement search inputs for user

Save the editor and you will land into another editor to decide the commit message of the melded three commits. In this editor, you will be given an option to add/remove the commit messages. Once you save the commit messages and quit the editor, all your commits will be transformed into one.

If you want to skip editing the commit message part, you can use fixup command and this will have your commit messages already commented out.

Once the commit message part is saved, the final thing you have to do is git push to push all your changes to remote. And this push has to be forced since the branch in your local and remote have been diverged after the rebase.

git push --force

P.S. If you have too many commits, to be squashed and you have manually update every pick to squash , vim provides a simple way to achieve it.

:%s/pick/squash/gc

This command will update every pick to squash upon your confirmation.

If you say reword ( r for short) in a commit you want to edit:

pick f796c1 Initial commit
pick 9f2adb Add feature to pipeline
reword ba6f1f Add listing feature to quality checks
pick 59c01d Add pyplot for better analysis
pick 8f4917 Enriched plots for better understanding
pick c88bc5 Implement search inputs for user
# Rebase 8db7e8b..fa20af3 onto 8db7e8b
#
# 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

When you save and quit the editor, git will follow the reword command and will land you in an editor again, as if you had amended commit ba6f1f . Now you can edit the commit message, save and quit the editor.

If you liked this article, click the 👏 so other people will see it here on Medium.

--

--