Software Engineering

How to Squash Commits in Git

Learn how to squash multiple Git commits into a single commit using interactive rebase to create a cleaner, more maintainable commit history.

By Inventive HQ Team

When you are working with version control, you may have multiple commits that you would like to combine into a single commit. Or perhaps you want to change their order, clean up your commit history, or prepare changes for a pull request. Git's interactive rebase feature makes this easy. For a quick reference of Git commands, check out our Git Command Reference tool.

Why Squash Commits?

Squashing commits is useful when you want to:

  • Combine multiple small commits into one meaningful commit
  • Clean up your commit history before merging to main/master
  • Group related changes together
  • Remove "work in progress" or "fix typo" commits
  • Create a cleaner, more professional commit history

Cleaner Commit History

One of the primary advantages of squashing commits is achieving a cleaner, more manageable commit log. This simplification helps anyone looking into the project history to grasp the significant changes without getting lost in a sea of minor updates.

Enhanced Collaboration

When working in a team, a tidy commit history can significantly improve the collaborative process. It reduces the complexity new members face when they join the project and helps maintain clarity about what changes have been made and why.

Easier Rollbacks

By consolidating multiple related changes into a single commit, it becomes easier to revert changes if something goes wrong. Instead of having to undo or fix several individual commits, developers can revert a single squashed commit, which can save a lot of time and reduce the risk of errors in the rollback process.

Preparing Your Branch

Before you begin the squash process, ensure your working branch is up-to-date and checked out:

# Switch to your feature branch
git checkout feature-branch

# Update your branch (if necessary)
git fetch origin
git rebase origin/main

Finding the Commits to Squash

First you need to determine how far back you want to go. Open a command prompt or terminal window, navigate to your Git Repository.

Next, type:

git log -10

The above command will show the last 10 commits. If that does not go far enough back, increase the number 10.

Starting Interactive Rebase

Once you have identified the commits you wish to squash, run the git rebase command:

git rebase -i HEAD~10

The above command will open a git rebase window showing you the last 10 commits. Adjust this number as needed.

Understanding the Rebase Interface

Each line shown will have the word "pick" at the beginning. Here is what the rebase window looks like:

pick abc1234 First commit message
pick def5678 Second commit message
pick ghi9012 Third commit message

# Rebase commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

Squashing Your Commits

Any commits you wish to squash, replace the word "pick" with the letter "s" (for squash) or "f" (for fixup).

Important guidelines:

  • Leave the first commit in the list set to "pick" - this is what other commits will be squashed into
  • Replace "pick" with "s" for commits you want to squash into the previous commit
  • Be sure to leave at least one commit as "pick" so there's something to squash into

For example, to squash the second and third commits into the first:

pick abc1234 First commit message
s def5678 Second commit message
s ghi9012 Third commit message

Editing the Combined Commit Message

After you save and close the rebase file, Git will prompt you to edit the combined commit message. You can:

  • Keep all the original commit messages
  • Write a new single message that describes all the changes
  • Delete unwanted messages and keep only the relevant ones

Completing the Rebase

Once you've edited the commit message and saved the file, Git will complete the rebase and your commits will be squashed together.

Important Notes

  1. Don't rebase published commits: Only squash commits that haven't been pushed to a shared repository, or be prepared to force push
  2. Force push carefully: If you've already pushed the commits, you'll need to force push: git push --force
  3. Backup your work: Consider creating a backup branch before rebasing: git branch backup-branch

Common Issues and Solutions

Issue: "Cannot 'squash' without a previous commit"

  • Solution: Make sure the first commit in your rebase list is set to "pick"

Issue: Merge conflicts during rebase

  • Solution: Resolve conflicts, then run git rebase --continue

Issue: Want to abort the rebase

  • Solution: Run git rebase --abort to return to the state before rebasing

Best Practices

Do's

  1. Squash commits before creating a pull request - Clean up your history before code review
  2. Squash during feature development - Consider squashing commits regularly throughout development rather than waiting until merge time
  3. Keep meaningful commit messages - When squashing, revise the commit message to reflect the overall impact of the combined changes
  4. Use descriptive commit messages - Explain the "why" not just the "what"
  5. Test before squashing - Make sure the branch is fully functional and tested before squashing
  6. Communicate with your team - Keep your team informed about your squashing plans in collaborative environments
  7. Consider your team's preferences - Follow your team's commit history conventions

Don'ts

  1. Don't squash commits that have already been merged to main - Respect the shared history
  2. Don't lose granular history - Be careful not to squash commits that contain important individual changes that may need to be tracked separately
  3. Don't squash shared commits - Never squash commits that have already been pushed to a shared repository where others might have based work on them
  4. Avoid excessive squashing - Don't squash commits indiscriminately—each squashed commit should still be meaningful and represent a logical unit of work

Mastering Git's rebase and squash features will help you maintain a clean, professional commit history that makes code review and debugging much easier.

Alternative Methods to Squash Commits

Method 1: Soft Reset

If interactive rebase feels complex, use soft reset for a simpler approach:

# Undo last 3 commits, keeping changes staged
git reset --soft HEAD~3

# Create a single new commit
git commit -m "Combined feature: description of all changes"

Method 2: Merge Squash

When merging a feature branch, squash all commits into one:

# From main branch
git merge --squash feature-branch
git commit -m "Add feature: complete description"

This is ideal for pull request workflows where you want to preserve the feature branch history but merge cleanly.

Method 3: GitHub/GitLab Squash Merge

Most Git platforms offer "Squash and merge" as a PR merge option. This automatically combines all PR commits into one when merging, without manual rebase.

Frequently Asked Questions

What does squash mean in Git?

Squashing in Git means combining multiple commits into a single commit. This is typically done using interactive rebase (git rebase -i) to clean up commit history before merging a feature branch. Squashing keeps your Git history readable by eliminating WIP commits, typo fixes, and intermediate work.

How do I squash the last 3 commits in Git?

Run git rebase -i HEAD~3 to open interactive rebase for the last 3 commits. Change 'pick' to 's' (squash) for the commits you want to combine into the first one. Save and close the editor, then edit the combined commit message. The 3 commits become 1 with a clean message.

What is the difference between squash and fixup in Git?

Both squash and fixup combine commits, but they handle commit messages differently. 'squash' (s) merges the commit and opens an editor to combine all commit messages. 'fixup' (f) merges the commit but discards its message, keeping only the target commit's message. Use fixup for commits like 'fix typo' that don't need their message preserved.

Can I squash commits that have already been pushed?

Yes, but you'll need to force push afterwards with git push --force or git push --force-with-lease. Warning: This rewrites history and can cause problems for collaborators who have pulled the original commits. Only squash pushed commits on feature branches you own, never on shared branches like main or master.

How do I squash commits without interactive rebase?

Use soft reset: git reset --soft HEAD~3 to undo the last 3 commits while keeping changes staged, then git commit -m 'New message' to create one commit. Or use git merge --squash branch-name when merging a feature branch to combine all its commits into one.

Why should I squash commits before a pull request?

Squashing creates a cleaner Git history that's easier to review, bisect for bugs, and understand later. Instead of seeing 15 commits like 'WIP', 'fix', 'more fixes', reviewers see one meaningful commit describing the complete feature. Many teams require squashing as part of their PR workflow.

What is the difference between reword and edit in interactive rebase?

'reword' (r) uses the commit but opens an editor to change only the commit message—the code changes remain the same. 'edit' (e) pauses the rebase at that commit, letting you modify the actual code, split it into multiple commits, or make any changes before continuing with git rebase --continue.

What happens to my commit timestamps when I squash?

When you squash commits, the resulting commit uses the timestamp of the oldest commit being squashed (the one marked 'pick'). The author date is preserved from the first commit. You can override this with git commit --amend --date='new date' after squashing if needed.

How do I abort a rebase if I make a mistake?

Run git rebase --abort at any point during an interactive rebase to completely cancel the operation and return to the state before you started. All your original commits will be restored. If you've already completed the rebase, use git reflog to find the previous HEAD and git reset --hard to return to it.

Can I squash only some commits in a range and keep others separate?

Yes, in interactive rebase you can mix 'pick' and 'squash' commands. Commits marked 'squash' merge into the commit above them (most recent 'pick'). Leave commits you want to keep separate as 'pick'. You can also reorder commits by moving lines before squashing to group related commits together.

gitversion controldevelopment workflowbest practices

Need help from an IT & cybersecurity partner?

InventiveHQ helps businesses secure, modernize, and run their technology. Let's talk about your goals.

Get in touch