Optimising commit History - squash in git for Beginners

Optimising commit History - squash in git for Beginners

Improving the commit history of a project by squashing them


5 min read

What is squashing commits?

Squashing commits means combining the changes of multiple commits of a branch into a single commit with the same or different commit message and a different ID.

When to squash commits?

Commits can be squashed to make the commit history of your code cleaner by combining multiple changes that may be related to a single application into a single commit thus maximizing ease of understanding the purpose of a commit and the changes it brings along.

How to Squash Your commits?

In this article, I'll focus on squashing commits using interactive rebase and git merge.

Squashing commits by the use of Interactive Rebase

To Squash the commit history of a repository using Interactive Rebase,

First of all, in the commit history get the number of commits from the latest commit, say n. For this enter interactive rebase using:

git rebase -i HEAD~n

This will open up a text editor that has the commit history which can be modified. The opened file will look like this:

pick 96045a4 test Commit
pick 9f8f4cd Push Meta, Sitemap

# Rebase 9394cc0..9f8f4cd onto 9394cc0 (12 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 [-C | -c] <commit> = like "squash" but keep only the previous
#                    commit's log message, unless -C is used, in which case
#                    keep only this commit's message; -c is same as -C but
#                    opens the editor
# 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.

Here I have 2 commits listed in my interactive rebase, in order of oldest first.

It seems obvious that 96045a4 test commit did not have much importance and can be easily considered to be squashed into others as the changes that this commit holds may not be having much value by themselves

To squash these commits, that is, to merge the second commit into the first one, just replace the pick with squash.

pick 96045a4 test Commit
squash 9f8f4cd Push Meta, Sitemap

On Proceeding, the editor for the commit message appears, something like this

# This is a combination of 2 commits.
# This is the 1st commit message:

test Commit

# This is the commit message #2:

Push Meta, Sitemap

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Date:      Fri Aug 11 15:13:31 2023 +0530
# interactive rebase in progress; onto 9394cc0
# Last commands done (12 commands done):
#    pick 96045a4 test Commit
#    squash 9f8f4cd Push Meta, Sitemap
# No commands remaining.
# You are currently rebasing branch 'main' on '9394cc0'.
# Changes to be committed:
#    modified:   .env.example
#    new file:   public/og.png
#    modified:   src/app/(auth)/login/layout.tsx
#    modified:   src/app/(static-pages)/documentation/page.tsx
#    modified:   src/app/(static-pages)/features/page.tsx
#    modified:   src/app/(static-pages)/layout.tsx
#    modified:   src/app/categories/layout.tsx
#    modified:   src/app/dashboard/layout.tsx
#    modified:   src/app/global-error.tsx
#    modified:   src/app/layout.tsx
#    new file:   src/app/loading.tsx
#    modified:   src/app/recipes/[id]/page.tsx
#    modified:   src/app/recipes/layout.tsx
#    new file:   src/app/sitemap.ts

Change the commit as may be wished/ agreed upon,
For this article, I'll squash them into a single commit. To do so, Change the pick to squash whichever commit has to be put.

# This is a combination of 2 commits.

Push Meta, Sitemap and merge test commit.

After making the relevant changes, save the file and close it to change the commit message. The status of the changes will be displayed after rebasing.

$ git rebase -i HEAD~12
[detached HEAD 84e40cb] Push Meta, Sitemap and merge site map
 Date: Fri Aug 11 15:13:31 2023 +0530
 14 files changed, 119 insertions(+), 22 deletions(-)
 create mode 100644 public/og.png
 create mode 100644 src/app/loading.tsx
 create mode 100644 src/app/sitemap.ts
Successfully rebased and updated refs/heads/main.

Finally, check the git log using git log the Latest commit that is in the log is:

commit 84e40cb307c28a92386101ac374a0e4047f4c553 (HEAD -> main)
Author: Raj Aryan <me@mmail.com>
Date:   Fri Aug 11 15:13:31 2023 +0530

    Push Meta, Sitemap and merge site map

To push the updated changes to your Github, Gitlab or BitBucket, use:

git push -f

Squashing Commits into one. git squash

Squashing commits is a powerful technique to maintain a clean and comprehensible Git history. By combining related changes into meaningful commits, you enhance collaboration, code reviews, and documentation efforts. Whether you opt for interactive rebase or git merge, squashing commits empower you to present a concise and organized narrative of your code's evolution.

Remember, a well-organized Git history is not just a technical nicety; it's a valuable asset that contributes to efficient collaboration and project management. So, the next time you find yourself navigating through a convoluted commit history, consider the benefits of squashing commits to bring clarity and order to your codebase. Happy coding!

Did you find this article valuable?

Support Raj Aryan by becoming a sponsor. Any amount is appreciated!