Skip to content

How to automatically squash Git commits

Alexander Graul edited this page Feb 25, 2025 · 1 revision

This is a walkthrough of two very useful Git features that allow reviewers to track what changed between reviews but still allow the author to create a nice history just before merging with a single command.

We start with a branch that's behind master (HEAD points to how-to-autosquash, i.e. 2f2c7c7c403).

~uyuni/uy-master[how-to-autosquash]
% git log --oneline -n 4 master
7b5a8febf3b (origin/master, origin/HEAD, master) ACL method for RBAC namespaces in struts
b023419ebd4 Fix unauthorized routes in ApiHandler
2f2c7c7c403 (HEAD -> how-to-autosquash) Implement authorization filters for spark, struts and ajax routes
34f4db2d621 Add experimental config flag for RBAC

We change something and commit it.

~uyuni/uy-master[how-to-autosquash]
% echo '\nThis is my meaningful chang.' >README.md
~uyuni/uy-master[how-to-autosquash]
% git add README.md 
~uyuni/uy-master[how-to-autosquash]
% git commit -m 'Really good stuff in this commit.'
[how-to-autosquash 7482eccb264] Really good stuff in this commit.
 1 file changed, 1 insertion(+), 24 deletions(-)

Now my attentive colleague reviews the change and screams

there is a typo, we can't accept that!

Well, that's something that is easily fixed.

~uyuni/uy-master[how-to-autosquash]
% sed -i 's/chang\./change./' README.md
~uyuni/uy-master[how-to-autosquash]
% git add README.md 
~uyuni/uy-master[how-to-autosquash]
% git commit --fixup=HEAD # change should be added to the last commit later on
[how-to-autosquash 8eafcd9eda5] fixup! Really good stuff in this commit.
 1 file changed, 1 insertion(+), 1 deletion(-)

This time the reviewer is happy

LGTM! Great contribution! It was so easy to review the individual commits.

And he is right, the difference between the first and the second review is in a single commit.

~uyuni/uy-master[how-to-autosquash]
% git show                  
commit 8eafcd9eda5c824fbeea519a55b9a621526a00ab (HEAD -> how-to-autosquash)
Author: Alexander Graul <[email protected]>
Date:   Tue Feb 25 14:09:51 2025 +0100

    fixup! Really good stuff in this commit.

diff --git a/README.md b/README.md
index 54dc38cafcb..c633cd95195 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
 
-This is my meaningful chang.
+This is my meaningful change.

Looking at the current branch, we now have two additional commits on top of 2f2c7c7c403, the commit that how-to-autosquash first pointed to.

~uyuni/uy-master[how-to-autosquash]
% git log --oneline -n 4
8eafcd9eda5 (HEAD -> how-to-autosquash) fixup! Really good stuff in this commit.
7482eccb264 Really good stuff in this commit.
2f2c7c7c403 Implement authorization filters for spark, struts and ajax routes
34f4db2d621 Add experimental config flag for RBAC

At this point we are almost ready. The code change is approved, all tests are good. There is just one tiny thing: there are still two commits. That's not really needed, the second just fixes a problem with the first. And the commit message is weird. Also, there were changes in master in the meantime:

~uyuni/uy-master[how-to-autosquash]
% git diff --name-only origin/master..HEAD
README.md
java/code/src/com/redhat/rhn/common/security/acl/Access.java
java/code/src/com/redhat/rhn/frontend/xmlrpc/api/ApiHandler.java
java/code/src/com/redhat/rhn/manager/user/UserManager.java
java/code/src/com/suse/manager/api/HttpApiRegistry.java
java/code/src/com/suse/manager/api/test/HttpApiRegistryTest.java
testsuite/features/support/http_client.rb

Let's fix that! Remember that I said we just need one command? Here it is:

~uyuni/uy-master[how-to-autosquash]
% git rebase --autosquash origin/master
Successfully rebased and updated refs/heads/how-to-autosquash.

For good measure, let's take a quick look at the git log again.

~uyuni/uy-master[how-to-autosquash]
% git log --oneline -n 5
ed8929931d1 (HEAD -> how-to-autosquash) Really good stuff in this commit.
7b5a8febf3b (origin/master, origin/HEAD, master) ACL method for RBAC namespaces in struts
b023419ebd4 Fix unauthorized routes in ApiHandler
2f2c7c7c403 Implement authorization filters for spark, struts and ajax routes
34f4db2d621 Add experimental config flag for RBAC
Clone this wiki locally