You would use “git squash” when you want to combine multiple commits into one single commit. The goal is to tidy up your commits usually.
To squash your commits, you can use “git rebase -i” first to get the list of commits in an editor, then change the commits from “pick” to “squash” for the commits that follow the first commit that you want to squash and then save. All the commits will squash into the commit that was above these.
Let us see this whole process step-by-step on a real machine.
The initial setup is as shown. Use “git log –oneline” to list all the commits in the repository “repoone“.
We aim to squash commits 3f54558, bead66e, 27658cf, and 9870df7 into one commit.
~/repoone$ git log --oneline d0978f9 (HEAD -> main, origin/main, origin/HEAD) Sixth line in newfile 9870df7 Update newfile 27658cf Fourth line added in newfile bead66e Another change to new file 3f54558 This is new file 4632c0d Adding empty directory 908d6ac Third commit in main 42296d0 Second commit in main 453424e This is first commit 2673111 Initial commit
Pick a commit that is older than these commits to list all the later commits in the editor. We chose 4632c0d so that git displays all the commits above in the editor.
~/repoone$ git rebase -i 4632c0d
Choose the three commits after the first commit, and change “pick” to “squash“.
pick 3f54558 This is new file squash bead66e Another change to new file squash 27658cf Fourth line added in newfile squash 9870df7 Update newfile pick d0978f9 Sixth line in newfile # Rebase 4632c0d..d0978f9 onto 4632c0d (5 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. #
Press Save or Close based on your editor and git setup. It would display a commit message.
# This is a combination of 4 commits. # This is the 1st commit message: This is new file # This is the commit message #2: Another change to new file # This is the commit message #3: Fourth line added in newfile # This is the commit message #4: Update newfile Fifth line in newfile # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Author: codeversionmaster <firstname.lastname@example.org> # Date: Sat Oct 15 21:25:35 2022 +0530 # # interactive rebase in progress; onto 4632c0d # Last commands done (4 commands done): # squash 27658cf Fourth line added in newfile # squash 9870df7 Update newfile # Next command to do (1 remaining command): # pick d0978f9 Sixth line in newfile # You are currently rebasing branch 'main' on '4632c0d'. # # Changes to be committed: # new file: newfile #
Press Save or Close based on your editor and git setup. It would display the rebase status as shown.
[detached HEAD 0516dab] This is new file Author: codeversionmaster <email@example.com> Date: Sat Oct 15 21:25:35 2022 +0530 1 file changed, 5 insertions(+) create mode 100644 newfile Successfully rebased and updated refs/heads/main.
Now you can list the commits using “git log –oneline“. The three commits marked as “squash” no more appear, and they got squashed into the commit just before them, i.e., the commit with the message “0516dab This is new file”.
~/repoone$ git log --oneline 378e483 (HEAD -> main) Sixth line in newfile 0516dab This is new file 4632c0d Adding empty directory 908d6ac Third commit in main 42296d0 Second commit in main 453424e This is first commit 2673111 Initial commit
You can do “git show” on the top commit of these three squashed commits. You can see it would have all the commit messages and changes.
~/repoone$ git show 0516dab commit 0516dabb7cb7a9f69f97d10bd66f5d44d5345058 Author: codeversionmaster <firstname.lastname@example.org> Date: Sat Oct 15 21:25:35 2022 +0530 This is new file Another change to new file Fourth line added in newfile Update newfile Fifth line in newfile diff --git a/newfile b/newfile new file mode 100644 index 0000000..66ac9df --- /dev/null +++ b/newfile @@ -0,0 +1,5 @@ +This is new file +Another change added to this file + +This is fourth line +This is fifth line