Back to Git & Dev Tools
2026-05-038 min read

Squash commits for a clean history (Git & Dev Tools)

Learn Squash commits for a clean history (Git & Dev Tools) step by step with clear examples and exercises.

Why This Matters

Maintaining a clean Git history is crucial for several reasons. A well-organized history makes it easier to understand the evolution of your project, trace changes, and collaborate with other developers effectively. Squashing commits helps achieve this by grouping related changes into a single commit with a meaningful message, reducing clutter and improving readability.

Prerequisites

To follow this lesson, you should have a basic understanding of Git and its commands, such as git add, git commit, and git push. Familiarity with the command line is also helpful but not necessary if you use a graphical user interface like GitHub Desktop or SourceTree. Additionally, it's essential to understand the concept of branches in Git and how to switch between them using commands like git checkout.

Core Concept

Squashing Commits: The Basics

To squash commits in Git, you'll typically want to combine multiple commits into one using the git rebase command. Here's a simple example of how this works:

  1. First, navigate to the branch you want to squash commits on with the git checkout command. For instance, if your branch is named my-feature, you would run:
git checkout my-feature
  1. Next, use the git rebase command to start an interactive rebase session. This will open a text editor with a list of commits in reverse chronological order:
git rebase -i HEAD~5

In this example, we're squashing the last five commits on our branch. You can adjust the number as needed.

  1. In the text editor, you'll see a list of commits with a pick command next to each one. To squash two or more consecutive commits, change the first pick to squash, and the subsequent picks to p. Save and close the file when you're done.
  1. Git will now open another text editor with a combined commit message for the squashed commits. Edit this message as needed, then save and close the file.
  1. Finally, Git will automatically create a new commit with your updated message and apply it to the branch. You can force push this commit to the remote repository using the git push --force command:
git push --force

Advanced Squashing Techniques

While the basic squash method works well for many situations, there are times when you might need more advanced techniques. For example, if you have commits that were made on different branches and need to be squashed together, or if you want to reword commit messages during the squash process. In these cases, you can use additional Git commands like git cherry-pick, git merge, and git rebase --continue.

Squashing Commits Across Branches

To squash commits from different branches, follow these steps:

  1. Merge the two branches using git checkout source-branch; git merge target-branch.
  2. Start an interactive rebase session on the resulting merged branch: git rebase -i HEAD~n, where n is the number of commits you want to squash.
  3. Follow the basic squashing process as described earlier.

Rewording Commit Messages During Squash

If you need to change commit messages during the squash process, you can do so by following these steps:

  1. Start an interactive rebase session as usual: git rebase -i HEAD~n.
  2. In the text editor, change the command for the commit whose message you want to modify from pick to edit. Save and close the file.
  3. Git will stop at the specified commit, allowing you to edit its message using a text editor of your choice. Make your changes, save and exit the editor, then continue the rebase session with git rebase --continue.
  4. Once the rebase is complete, force push the updated commits to the remote repository: git push --force.

Worked Example

Let's walk through a worked example of squashing commits using the basic method described earlier. We'll assume you have a branch named my-feature with three commits:

  1. Commit A - Add initial feature implementation
  2. Commit B - Fix a bug in the feature
  3. Commit C - Improve user interface for the feature

To squash these commits, follow these steps:

  1. Checkout the branch:
git checkout my-feature
  1. Start an interactive rebase session:
git rebase -i HEAD~3
  1. In the text editor, you'll see a list of commits like this:
pick Commit A (initial feature implementation)
pick Commit B (fix bug)
pick Commit C (improve UI)
  1. Change the first pick to squash, and the subsequent picks to p. Save and close the file:
squash Commit A (initial feature implementation)
pick Commit B (fix bug)
pick Commit C (improve UI)
  1. Git will open another text editor with a combined commit message for the squashed commits:
If you have changed the merge message, please delete it and enter a new one here.
Squash: Add initial feature implementation, fix bug, improve UI
  1. Edit this message as needed, then save and close the file:
Squash: Implement feature, fix bug, improve UI
  1. Git will automatically create a new commit with your updated message and apply it to the branch:
Successfully rebased and updated refs/heads/my-feature.
  1. Finally, force push this commit to the remote repository:
git push --force

Common Mistakes

Forgetting to Force Push

The most common mistake when squashing commits is forgetting to use the git push --force command after rewriting commit history. If you don't force push, Git will refuse to accept your new commits because they conflict with the existing ones in the remote repository.

Squashing Too Many Commits at Once

Squashing too many commits at once can make it difficult to understand the changes made in each commit. It's generally a good idea to squash no more than three or four consecutive commits at a time, so that the combined commit message remains clear and informative.

Using the Wrong Rebase Command

When starting an interactive rebase session, it's essential to use the correct git rebase command. If you use git rebase HEAD, Git will create a new branch instead of modifying the current one. Always use git rebase -i HEAD~n, where n is the number of commits you want to squash, to ensure you're modifying the correct branch.

Squashing Commits Across Branches

When squashing commits from different branches, it's important to merge the branches before starting the rebase session. Failing to do so can result in conflicts that must be resolved manually.

Rewording Commit Messages During Squash

If you need to change commit messages during the squash process, make sure you save and close the text editor after editing the combined message. If you forget to save or close the file, Git will not apply the changes, and you'll need to start the rebase session again.

Practice Questions

  1. You have a Git branch with five commits that need to be squashed together. What command would you use to start an interactive rebase session?
git rebase -i HEAD~5
  1. You have two commits on different branches that need to be squashed together. How can you accomplish this using Git commands?
  • First, merge the two branches: git checkout branch1; git merge branch2.
  • Then, follow the basic squash method described in the lesson.
  1. You've squashed some commits and want to reword the combined commit message. What command would you use to edit the message?
  • After saving and closing the file during the interactive rebase session, Git will automatically open another text editor with the combined commit message. Edit this message as needed, then save and close the file.
  1. You've squashed some commits but realize that one of them should have been a separate commit. How can you undo the squash for that specific commit?
  • Use git reflog to find the original commit hash, then create a new branch or reset your current branch to that commit: git checkout -b new-branch .
  • Once on the new branch, start an interactive rebase session with git rebase -i ^, change the command for the squashed commit from squash back to pick, and continue the rebase session.

FAQ

Q: Can I squash commits on a remote repository directly?

A: No, you cannot squash commits on a remote repository directly. You must first fetch or pull the changes from the remote repository to your local machine and then perform the squash operation locally. Once you've rewritten the commit history, you can force push the changes to the remote repository using git push --force.

Q: What happens if I forget to use git add before starting an interactive rebase session?

A: If you forget to git add any untracked files or modified files before starting an interactive rebase session, those changes will be lost when you squash the commits. To avoid this, always make sure all changes are added and committed before starting a rebase session.

Q: Is it possible to undo a squashed commit?

A: Yes, it's possible to undo a squashed commit using Git commands like git reflog or git reset. However, keep in mind that undoing a squashed commit can be complex and may require careful attention to avoid creating additional problems. It's always best to squash commits thoughtfully and only when necessary.

Q: How do I squash multiple commits from different branches without merging them first?

A: To squash commits from different branches without merging them first, you can use the git cherry-pick command. Follow these steps:

  1. Start a new branch based on the source branch: git checkout -b new-branch source-branch.
  2. Cherry-pick the target commits from the target branch onto the new branch: git cherry-pick ...
  3. Start an interactive rebase session on the new branch: git rebase -i HEAD~n, where n is the number of commits you want to squash.
  4. Follow the basic squashing process as described earlier.
Squash commits for a clean history (Git & Dev Tools) | Git & Dev Tools | XQA Learn