What Is the Difference Between a Merge Commit & a Squash?
Git and GitHub can be tricky tools to master, but the better you get at using them, the more secure and consistent your coding work can become. Developers around the world leverage a number of Git and GitHub workflows to streamline their progress. Some of these incorporate squash merges to simplify collaboration, but you'll need to know what makes squashes any different from a regular merge commit first to get the most out of them.
What is a standard merge in Git? 🕵🏼♀️
Merging is one of the most important actions you can take when you're using Git. Whenever your project's history splits (or "forks"), there’s a high likelihood of each branch diverging from the other during the development process. Merging makes it possible to reconcile each branch's differences with a shared branch, consolidating all of the work you and your team members have done into a single codebase that can be traced all the way back to its inception. Pretty neat, right? Considering the above is basically what Git was made to do, it wouldn't be too much of a stretch to suggest that merging is practically at the very core of Git itself.
Git tracks commits to a branch over time and allows for a special merge commit to be made. This merge commit combines the parent commits located directly after the most recent common commit on both the current branch and the branch to be merged. There are multiple variations of this basic merging process that alter the results of the operation. However, you can generally expect merge commits to add commits from a target branch to the branch you currently have checked out.
Merges happen locally 🎯
Whenever you merge in Git, you do so with a local repository. You can track changes in remote repos locally or fetch them as needed to perform merging operations, but all changes, including your merge commits, will need to be pushed to your remote repo once you’ve completed them. Naturally, as this entire process is inherently complex, it carries a few drawbacks. The most relevant of these is the fact that every single commit that has been made on a given feature branch will be merged with the master via the merge commit. This can lead to a rather messy main branch and a minor headache for anyone tasked with reading it. Thankfully, there’s a way to clear out all of the clutter and make merge commits much simpler to read through: the squash merge.
What is a squash merge in Git? 🔍
A squash merge is meant to simplify and summarize the commits that have taken place in your feature branch, yet the operation itself creates no commit at all in your branch's history. Although this may seem counterintuitive, it works when you need to set up changes in your local repo that can then be committed manually. More specifically, squashing during a merge generates the working tree and index state to match a merge without actually creating a merge commit. You can then use git commit
to handle the rest on your own as everything has been prepared automatically. Squashing can be chosen as an option while merging in Git by adding --squash
to your merge command. Squashing can also be overridden with --no-squash
.
GitHub does it differently 🤠
GitHub offers up a useful option to handle squash merging operations for you automatically whenever you want it to. Squashing and merging is one of three options for merging on GitHub—alongside simple merging as well as rebasing and merging. When you perform this operation through GitHub, the details are abstracted away for convenience. You can count on GitHub to perform the initial squash and create a merge commit to go along with it. You can create a custom squashed commit message or allow GitHub to generate its own.
When to squash and when not to squash 🧐
Squashing can certainly come in handy for teams and projects that need clarity and less clutter from myriad commits. However, using squash for every merge is not necessarily an ideal strategy—some teams risk losing valuable information from individual commits when they choose this approach.
You should consider using squash if your team prefers a linear project history. This means that the history held by your main branch should not contain merges. A squash merge makes it possible to keep changes condensed to a single commit, supporting this strategy nicely. Teams looking to keep pull requests down to a single commit when merged will find great utility in the squash and merge operation as well. Of course, handling merging operations all day is no way for a developer to live. Luckily, there's a solution for that too.
How to keep consistency
GitHub allows you to configure if a repository should accept or not squash commits. However, if you want to use different merge methods based on different criteria, it turns out to be impossible to configure this in GitHub.
Mergify can help 🥰
This is a situation where Mergify can shine. By writing pull request rules, you can automatically merge pull requests using the right merge method.
Sign up for a quick demo to discover just how useful Mergify can be for your team today.