How to Squash Git Commits

28/12/2020
Git

How to Squash Commits in Git to Keep Your History Clean

When you are working with Git, it’s a good idea to commit often, so you can always go back to the state of the code if you mess up. However, committing all those mini-changes to the main branch is not always a good idea. It makes the history messy and hard to follow.

Git provides a way to squash a bunch of your commits using the rebase command. Once you have locally made your changes to a particular file or for a particular feature, you can always use the squash method to combine the changes together before you commit to the main branch. This will help other understand your changes better.

Warning: Even though you can pull from external repositories and squash commits together, it’s a bad idea. It can create conflicts and confusion. Avoid changing history that is already public. Only stick to squashing commits that are local to your work.

Let’s work through an example case.

Suppose, we have two files a.py and b.py. Let’s first go through the process of creating the files and making the modifications:

$ mkdir myproject
$ cd myproject/
$ git init
$ echo "print("hello A")" > a.py
$ git add -A && git commit -m "Added a.py"
$ echo "print("hello B")" > b.py
$ git add -A && git commit -m "Added b.py"
$ echo "print("hello BB")" > b.py
$ git add -A && git commit -m "b.py Modification 1"
$ echo "print("hello BBB")" > b.py
$ git add -A && git commit -m "b.py Modification 2"

If we check the history of commits, we will see the following:

$ git log –oneline –graph –decorate
* dfc0295 (HEAD –> master) b.py Modification 2
* ce9e582 b.py Modification 1
* 7a62538 Added b.py
* 952244a Added a.py

After we are done with our work, we decide to put all the changes to the b.py into a single commit for clarity. We count that there are 3 commits on b.py from the HEAD. We issue the following command:

git rebase -i HEAD~3

The -i option tells Git to use the interactive mode.

It should pop up a window on your Git text editor:

pick 7a62538 Added b.py
pick ce9e582 b.py Modification 1
pick dfc0295 b.py Modification 2
 
# Rebase 952244a..dfc0295 onto 952244a (3 command(s))
#
# 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
~

The commits are listed chronologically on the top from the earliest to the most recent. You can choose which commit to “pick” and which commits to squash. For simplicity, we will pick the first commit and squash the rest into it. So we will modify the text like this:

pick 7a62538 Added b.py
squash ce9e582 b.py Modification 1
squash dfc0295 b.py Modification 2
 
# Rebase 952244a..dfc0295 onto 952244a (3 command(s))
#
# 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

As soon as you save and close the text file, another text window should pop up that looks like this:

# This is a combination of 3 commits.
# The first commit’s message is:
Added b.py
 
# This is the 2nd commit message:
 
b.py Modification 1
 
# This is the 3rd commit message:
 
b.py Modification 2
 
# Please enter the commit message for your changes. Lines starting
# with ‘#’ will be ignored, and an empty message aborts the commit.
#
# Date:      Fri Mar 30 21:09:43 2018 -0700
#
# rebase in progress; onto 952244a
# You are currently editing a commit while rebasing branch ‘master’ on ‘952244a’.
#
# Changes to be committed:
#       new file:   b.py
#

Save and close this file too. You should see something like this:

$ git rebase -i HEAD~3
[detached HEAD 0798991] Added b.py
Date: Fri Mar 30 21:09:43 20180700
1 file changed, 1 insertion(+)
create mode 100644 b.py
Successfully rebased and updated refs/heads/master.

If you check the commit history now:

$ git log –oneline –graph –decorate
* 0798991 (HEAD –> master) Added b.py
* 952244a Added a.py

All the commits for b.py have been squashed into one commit. You can verify by looking at the b.py file:

$ cat b.py
print("hello BBB")

It has the content of Modification 2.

Conclusion

The rebase is a powerful command. It can help you keep your history clean. But avoid using it for already public commits as it can cause conflicts and confusion. Only use it for your own local repository.

Further Study:

ONET IDC thành lập vào năm 2012, là công ty chuyên nghiệp tại Việt Nam trong lĩnh vực cung cấp dịch vụ Hosting, VPS, máy chủ vật lý, dịch vụ Firewall Anti DDoS, SSL… Với 10 năm xây dựng và phát triển, ứng dụng nhiều công nghệ hiện đại, ONET IDC đã giúp hàng ngàn khách hàng tin tưởng lựa chọn, mang lại sự ổn định tuyệt đối cho website của khách hàng để thúc đẩy việc kinh doanh đạt được hiệu quả và thành công.
Bài viết liên quan

Git – Push Changes to Remote Git Branch

In this article, I am going to show you how to push (upload) your local Git repository to a remote Git repository hosted...
29/12/2020

Install GitLab on Ubuntu 18.04

With the recent acquisition of GitHub by Microsoft, many corporations and organisations have decided to migrate away from...
28/12/2020

PyCharm Git Integration

Over time, Git has turned out to be one of the most popular Open Source Version Control Systems of today. Its speed, simplicity,...
29/12/2020
Bài Viết

Bài Viết Mới Cập Nhật

Dịch Vụ Xây Dựng Hệ Thống Peering Với Internet Exchange (IXP)
04/04/2025

Dịch Vụ Triển Khai VPN Site-to-Site & Remote Access
04/04/2025

Dịch Vụ Thiết Lập Hệ Thống Tường Lửa (Firewall)
04/04/2025

Dịch Vụ Triển Khai Hệ Thống Ảo Hóa & Cloud
04/04/2025

Dịch Vụ Triển Khai Hệ Thống Ceph
04/04/2025