Git, squashing vs not squashing
In Git, there are 2 things:
- concepts: facts, principles, fundamentals that never change and there’s no debate over them
- opinions: things that are left to us to decide and there’s debate over them all of the time
An example of case 1 is commits, branches, merging, rebasing.
An example of case 2 is “rebase vs merge”.
Let’s talk about squashing.
As a concept, squashing is simple: we can take 2 or more commits we already committed to a branch, and squash them together.
As an opinion, the question is “when should you squash commits?” But also, “should you even squash commits at all”?
In Git many things are opinions, and depending on the context you can have your own opinion, for example when you’re working on your own on your private Git repository.
Other times you have conventions and decisions that have been taken by a project manager and you just follow them.
There’s endless discussion but no right or wrong, but we can point out advantages and disadvantages depending on the situation.
Being in “opinions” space, here I’ll show my own opinions.
Case 1: working on your own
Let’s say you’re working on your own repo, or perhaps a branch you haven’t pushed yet to remote, you can squash commits together as you prefer. I do this all the time, when working on my projects. In this case you got complete freedom. Maybe you committed something, then realized you had a bug, then tried some other solutions until you got it working, and now you just want a cleaner history that says “Implemented feature X” instead of a list of commits that shows you the process.
After all what matters is the end result.
Go ahead.
You don’t need to squash commits, but it’s not a big deal and if this gives you a better taste when looking at your branch history, then go ahead.
Case 2: working on a feature branch on your own
Let’s say you are working on a feature branch. Before merging to main you should rebase all your commits upon main (another opinion), but you can also squash commits together, so that instead of looking at a long big list of commits you did to implement the feature, you just have a single commit.
The benefit of doing so is that you can very easily revert changes by reverting a single commit. It feels cleaner.
It’s so useful that GitHub offers this option in the workflow when you merge a Pull Request.
The downside is more philosophical and emotional: you worked so hard for 2 weeks on a feature branch adding a ton of commits with nice commit messages and descriptions, and now all of that work is going away because you’ll have a single commit in the Git history, which by its nature will never be as detailed and descriptive as many individual commits, unless of course you craft a well prepared Pull Request description on GitHub (assuming you use GitHub).
Perhaps the real work you did was trying 10 different changes to an algorithm to make it faster, and the solution is like 2 lines of code. Squashing doesn’t show you all the work you did before, so the “proof” (so to speak) of your work is now gone.
If you’re one of those people that likes to see their GitHub “streak” graph full of commits, squashing and then merging into main and then deleting the feature branch will delete a ton of activity. Vanity metrics, I know, perhaps you don’t care (<be-honest-david-beckham.gif>), but perhaps this is really motivating to make you “show up every day” and do the work day in day out.
In this case what I would do is squashing commits along the way if needed, using a good commit “schedule” and writing descriptive commit messages, but when it’s time to merge into the main branch, leave the history intact to keep the progress visible.
To easily revert to a state before the feature branch was merged, use tags.
Case 3: working on a feature branch with team members
Expanding on the previous case, suppose you and 2 other team members work on a feature branch for a week, you each write 10 commits, perhaps someone worked even more than you, but you get to do the squashing.
Now it seems like you did all the work, because there’s just one commit with your name attached.
I don’t think this is right.
First, it’s important for everyone to have their contribution “set in stone”, so to say.
But also, tools like git blame
can be very useful down the line, months or years from now, to say “person X did this, let me talk to them why they chose this approach” and find information that sometimes is not written in a comment or documented anywhere else.
By squashing, they’d ask you, but you have no idea, since all you did was squashing someone else’s commits.
Case 4: squashing on a remote branch
While you can squash commits on a remote branch, I think this is one of the things you should not do even if Git makes them technically possible, to prevent possible issues.
Especially if you know other people work on the same branch as well, and they already pulled the code to work on it.
Unless you absolutely need to, for some reason.
But if you did something wrong (perhaps you meant to squash before but then realized you didn’t), or someone else did something wrong (perhaps a junior team member on their 1st day on the job), learn the lesson for the future and find ways to prevent this from happening again
Imho.
Conclusion
Squashing can be really useful a lot of times. Use with judgment and caution though, as different scenarios can have different ideal solutions.
→ I wrote 17 books to help you become a better developer:
- C Handbook
- Command Line Handbook
- CSS Handbook
- Express Handbook
- Git Cheat Sheet
- Go Handbook
- HTML Handbook
- JS Handbook
- Laravel Handbook
- Next.js Handbook
- Node.js Handbook
- PHP Handbook
- Python Handbook
- React Handbook
- SQL Handbook
- Svelte Handbook
- Swift Handbook
Also, JOIN MY CODING BOOTCAMP, an amazing cohort course that will be a huge step up in your coding career - covering React, Next.js - next edition February 2025