Programming

What does it mean to squash commits in git

19 September 2026 · 13 min read

What does it mean to squash commits in git

Working with Git can sometimes feel like navigating a complex maze, especially when dealing with numerous commits. One technique that can significantly streamline your Git history is to squash commits. But what does it mean to squash commits in Git, and why would you want to do it? Simply put, squashing commits combines multiple commits into a single, cleaner commit. This process is particularly useful when you have a series of small, incremental commits that, when viewed individually, don’t provide much context or value. Instead of cluttering your project’s history with these minor changes, squashing allows you to present a more cohesive and understandable narrative of the development process. Think of it as editing a rough draft into a polished final version, making it easier for others (and your future self) to understand the evolution of your code. This article will delve into the mechanics of commit squashing, its benefits, and how to effectively implement it in your Git workflow. Understanding how to manipulate your commit history in this way is a powerful tool for any developer aiming to maintain a clean and understandable project repository.

Understanding the Basics of Git Commits

Before diving into the specifics of squashing commits, it’s crucial to understand what Git commits are and how they function. A Git commit is essentially a snapshot of your project at a particular point in time. Each commit includes metadata such as the author, committer, date, and a descriptive message. These commits form a chronological history of changes, allowing developers to track modifications, revert to previous versions, and collaborate effectively. However, this detailed history can sometimes become noisy, especially when developers create numerous commits for small, incremental changes, such as fixing typos or making minor adjustments to code. These small commits, while individually helpful during development, can clutter the project’s history and make it harder to understand the bigger picture.

Git commits also serve as a crucial part of the branching and merging process. When multiple developers work on different features simultaneously, they often create separate branches. These branches are later merged back into the main branch. A clean commit history is essential for a smooth and understandable merge. Too many small, insignificant commits can make the merge process more complex and increase the risk of conflicts. In contrast, a well-structured commit history, achieved through techniques like commit squashing, simplifies the merge process and reduces the likelihood of introducing errors. Consider it as organizing your notes before writing an essay; a structured approach saves time and ensures a coherent final product. Git uses SHA-1 hashes to uniquely identify each commit, ensuring data integrity and providing a reliable audit trail of all changes made to the project.

Keeping the commit history clean contributes to better collaboration and easier maintenance. When new developers join a project, they often need to understand the history of the codebase. A clean, well-documented commit history makes it easier for them to grasp the project’s evolution and contribute effectively. Tools like git log and graphical interfaces like GitKraken or SourceTree become much more useful when the commit history is organized and concise. The goal is to create a history that tells a story, making it easier for anyone to understand the reasons behind each change and the overall direction of the project. This is where strategies like interactive rebase and commit amending come into play, offering developers the flexibility to refine their commit history.

Why Squash Commits? The Benefits Explained

Squashing commits offers several significant advantages, primarily related to code clarity and maintainability. One of the most compelling reasons to squash commits is to create a cleaner, more understandable Git history. When a series of small, related changes are consolidated into a single commit, it becomes easier to grasp the purpose and impact of those changes. This is particularly useful when reviewing code or trying to understand the evolution of a specific feature. Think of it like writing a book; instead of having a collection of fragmented notes, you present a well-structured narrative. A cleaner history improves code review efficiency, reduces cognitive load, and fosters better collaboration among developers. This ties directly into improved repository hygiene.

Another benefit of squashing commits is that it simplifies the process of reverting changes. If you need to undo a feature or a set of changes, it’s much easier to revert a single, well-defined commit than to identify and revert multiple smaller commits. This reduces the risk of accidentally undoing unrelated changes and makes the reversion process more reliable. Moreover, a cleaner commit history makes it easier to identify the root cause of bugs or issues. When you can quickly trace the history of a piece of code, you can pinpoint when and why a particular change was introduced, making it easier to debug and fix problems. According to a study by GitHub, projects with well-maintained Git histories tend to have fewer bugs and faster resolution times Source: GitHub Resources.

Furthermore, squashing commits can improve the overall aesthetics and professionalism of your project. A clean commit history demonstrates attention to detail and a commitment to code quality. This can be particularly important when working on open-source projects or collaborating with external teams. A well-organized repository inspires confidence and makes it easier for others to contribute. It also reduces the barrier to entry for new developers who may be intimidated by a messy or convoluted history. In essence, squashing commits is about presenting your work in the best possible light and creating a positive impression on anyone who interacts with your project. The featured snippet below highlights the primary reason for squashing commits:

Squashing commits is primarily done to create a cleaner and more understandable Git history. By combining multiple small or incremental commits into a single, cohesive commit, developers can present a clearer narrative of the changes made to the codebase, making it easier to understand, review, and revert changes when needed.

How to Squash Commits: A Step-by-Step Guide

Now that you understand the benefits of squashing commits, let’s walk through the process of how to do it using Git. The most common method involves using Git’s interactive rebase feature. This feature allows you to manipulate your commit history in a variety of ways, including squashing, rewording, and deleting commits. The process might seem daunting at first, but once you understand the basic steps, it becomes a straightforward and powerful tool. The first step is to identify the commits you want to squash. Typically, you’ll want to squash a series of related commits that represent a single logical change or feature. To begin the interactive rebase, use the following command:

git rebase -i HEAD~n

Where n is the number of commits you want to include in the rebase. For example, if you want to squash the last three commits, you would use git rebase -i HEAD~3. This command opens a text editor with a list of the commits you’ve selected. Each commit is listed with the word “pick” in front of it. To squash a commit, change the word “pick” to “squash” (or just “s”). The first commit in the list should remain as “pick” – this will be the base commit to which the other commits will be squashed. Once you’ve made the necessary changes, save the file and close the editor. Git will then start the rebase process, and you’ll be prompted to enter a new commit message for the squashed commit. This message should accurately describe the combined changes from all the squashed commits.

Here’s a step-by-step breakdown of the process:

  1. Identify the commits you want to squash.
  2. Run git rebase -i HEAD~n, replacing n with the number of commits.
  3. In the text editor, change “pick” to “squash” for the commits you want to combine.
  4. Save and close the editor.
  5. Enter a new, descriptive commit message for the squashed commit.
  6. If conflicts arise during the rebase, resolve them and use git rebase --continue.
  7. Once the rebase is complete, use git push --force (if necessary) to update the remote repository. Be cautious with force pushing, as it can overwrite changes made by others.

It’s important to note that squashing commits modifies your commit history. This can be problematic if you’ve already pushed your changes to a shared remote repository. In such cases, you may need to use the git push --force command to overwrite the remote history. However, use this command with caution, as it can potentially overwrite changes made by other developers. It’s generally best to squash commits before pushing your changes to a shared repository, or to coordinate with your team to avoid conflicts. Remember to always communicate effectively with your team when making changes to shared branches. You can also use git merge –squash for an alternative approach. For further reading on best practices, consult the official Git documentation Source: Git Documentation.

Best Practices and Considerations for Squashing

While squashing commits can be a powerful tool, it’s essential to use it responsibly and with consideration for your team. One of the most important best practices is to avoid squashing commits that have already been shared with others. Once commits have been pushed to a shared remote repository, modifying their history can create conflicts and confusion for other developers. It’s generally best to squash commits in your local branch before pushing them to the remote. If you do need to modify shared commits, communicate clearly with your team and ensure that everyone understands the implications of your changes. A good practice is to use feature branches and squash commits within those branches before merging into the main branch. This isolates the changes and minimizes the risk of conflicts.

Another consideration is the granularity of your squashed commits. While it’s generally a good idea to combine small, incremental changes, you should avoid squashing commits that represent distinct logical units of work. Each commit should ideally represent a single, coherent change that can be easily understood and reverted if necessary. Overly large or complex commits can be difficult to review and debug. Strive for a balance between conciseness and clarity. For example, if you’re working on a new feature, you might have separate commits for implementing the core functionality, adding tests, and updating documentation. These commits could be squashed into a single commit that represents the complete feature. Aim for atomic commits as a guiding principle.

Here are some key takeaways to keep in mind:

  • Avoid squashing commits that have already been shared with others.
  • Ensure that each squashed commit represents a single, coherent change.
  • Write clear and descriptive commit messages for your squashed commits.

Furthermore, always write clear and descriptive commit messages for your squashed commits. The commit message should accurately describe the combined changes from all the squashed commits. Avoid generic or vague commit messages like “Fixed bug” or “Updated code.” Instead, provide specific details about the problem you solved or the changes you made. A well-written commit message makes it easier for others to understand the purpose and impact of the commit. According to Atlassian, well-crafted commit messages significantly improve team collaboration and code maintainability Source: Atlassian Git Tutorials. Remember to use meaningful commit messages.

Infographic here
Common Scenarios and Use Cases ------------------------------

Squashing commits is particularly useful in several common development scenarios. One frequent use case is when working on feature branches. As you develop a new feature, you may create numerous small commits as you iterate and refine your code. Before merging the feature branch into the main branch, it’s often a good idea to squash commits into a single, well-defined commit that represents the complete feature. This makes the history of the main branch cleaner and easier to understand. For example, imagine you’re adding a new user authentication system to your application. You might have separate commits for implementing the login form, handling password resets, and integrating with a third-party authentication provider. Squashing these commits into a single “Implement user authentication system” commit provides a clear and concise record of the feature’s implementation. This process directly relates to feature branch workflow.

Another common scenario is when fixing bugs or addressing technical debt. You might create several small commits as you investigate and resolve an issue. Before pushing your changes, you can squash these commits into a single commit that describes the bug fix or the technical debt remediation. This makes it easier to track the progress of bug fixes and ensures that the commit history accurately reflects the work that was done. For instance, suppose you discover a security vulnerability in your application. You might have separate commits for identifying the vulnerability, implementing a fix, and adding a security test. Squashing these commits into a single “Fix security vulnerability” commit provides a clear and concise record of the remediation effort. This contributes to improved code maintainability.

Squashing commits can also be helpful when collaborating with others on a project. If you’re working on a shared branch, you may want to squash your commits before pushing them to the remote repository. This helps to keep the branch history clean and organized, making it easier for others to understand your changes. However, as mentioned earlier, it’s essential to communicate with your team before squashing commits that have already been shared. Coordinate your efforts to avoid conflicts and ensure that everyone is on the same page. The key is to balance Question & Answer :

What does squashing commits in git mean? How do I squash commits in Github?

You can think of Git as an advanced database of snapshots of your working directory(ies).

One very nice feature of Git is the ability to rewrite the history of commits.
The principal reason for doing this is that a lot of such history is relevant only for the developer who generated it, so it must be simplified, or made more nice, before submitting it to a shared repository.

Squashing a commit means, from an idiomatic point of view, to move the changes introduced in said commit into its parent so that you end up with one commit instead of two (or more).
If you repeat this process multiple times, you can reduce n commit to a single one.

Visually, if you started your work at the commit tagged Start, you want this

Git commits squashing

You may notice that the new commit has a slightly darker shade of blue. This is intentional.

In Git squashing is achieved with a Rebase, of a special form called Interactive Rebase.
Simplifying: when you rebase a set of commits into a branch B, you apply all the changes introduced by those commits as they were done, starting from B instead of their original ancestor.

A visual clue

enter image description here

Note again the different shades of blue.

An interactive rebase let you choose how commits should be rebased. If you run this command:

git rebase -i branch 

You would end up with a file that lists the commits that will be rebased

pick ae3... pick ef6... pick 1e0... pick 341... 

I didn’t name the commits, but these four ones are intended to be the commits from Start to Head

The nice thing about this list is that it is editable.
You can omit commits, or you can squash them.
All you have to do is to change the first word to squash.

pick ae3... squash ef6... squash 1e0... squash 341... 

If you close the editor and no merge conflicts are found, you end up with this history:

enter image description here

In your case, you don’t want to rebase into another branch, but rather into a previous commit.
In order to transform the history as shown in the very first example, you have to run something like

git rebase -i HEAD~4 

change the “commands” to squash for all the commits apart from the first one, and then close your editor.


Note about altering history

In Git, commits are never edited. They can be pruned, made not reachable, cloned but not changed.
When you rebase, you are actually creating new commits.
The old ones are not longer reachable by any refs, so are not shown in the history but they are still there!

This is what you actually get for a rebase:

enter image description here

If you have already pushed them somewhere, rewriting the history will actually make a branch!