10. Git Squash

squash : squeeze, flatten, compress, crush.
squash is a process where we compress/merge multiple commits into one.

  • There is no git squash command, Rather, git reset or git rebase used for this
# Assume we want to squash from <commit>+1 upto HEAD.
# We need to move HEAD to <commit> but don't change current stash/work tree.
# Then commit the files and force push!
git reset --soft <commit> 
git commit -am "squashing"
git push --force origin HEAD

OR Another way us to use rebase as shown below. Using rebase, we can squash any two or contiguous commits. Though this is not much the case. Personally I find, reset is much simpler!

git rebase -i <AFTER_THIS_commit>

Note: Git lists the all commits after the given commit. If we want to squash commit X, we need to give X-1 commit hash

10.1 Commands

Git rebase log example.

_____________________________
#git log --oneline
3d671b7 (HEAD -> main) c6
1cd67d3 c5
8f0f877 c4
5a484d5 c3
1352bec c2
db82de0 c1
84a8c81 reworded: old
cabee39 (origin/main, origin/HEAD) Create blank.yml
37bd5d5 first commit
#___________________________
#git rebase -i  84a8

 1 pick db82de0 c1
 2 pick 1352bec c2
 3 pick 5a484d5 c3
 4 pick 8f0f877 c4
 5 pick 1cd67d3 c5
 6 s 3d671b7 c6
 7
 8 # Rebase 84a8c81..3d671b7 onto 84a8c81 (6 commands)
___________________________________
#git log --oneline
083c017 (HEAD -> main) c5+c6
8f0f877 c4
5a484d5 c3
1352bec c2
db82de0 c1
84a8c81 reworded: old
cabee39 (origin/main, origin/HEAD) Create blank.yml
37bd5d5 first commit
  • git presents the editor with commits sorted from OLDEST to NEWEST(Latest).
  • Logically, we need to start from oldest commit id to newer ones, since that is how time and code delivery progressed.
  • When we say squash a commit, it means, squash that into its previous one in time. (Not into its next one in time). This is also same in the editor given. in Editor, if we say, squash a commit id, it will squashed into commit id of the physical previous line. This is reason why git displays list of commit ids from the old to newest , not the newest to oldest. Also, as we saw earlier, work also happened old time to new time. This is even more fundamental reason.
  • i.e., Only Newer commits can be squashed into older commits. Not the other way
  • i.e., Hence, we can never squash oldest commit, which is at the top most row in above log .
  • Once a commit is chooses for Squash, the commit log editor will be given. The order is also same... Older commit to newer commit. Clean all lines, even blank lines if not needed. Give only one better commit message and delete all

10.2 References

10.3 - https://www.git-tower.com/learn/git/faq/git-squash