Home/Blog/Mastering Git: How to Squash Commits and Streamline Your History
Software Engineering

Mastering Git: How to Squash Commits and Streamline Your History

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
Mastering Git: How to Squash Commits and Streamline Your History

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.

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

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

  1. Squash commits before creating a pull request
  2. Keep meaningful commit messages in the final squashed commit
  3. Don't squash commits that have already been merged to main
  4. Use descriptive commit messages that explain the "why" not just the "what"
  5. Consider your team's commit history preferences before squashing

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

Frequently Asked Questions

Find answers to common questions

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.

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.

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.

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.

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.

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.

'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.

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.

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.

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.

Engineering Excellence for Your Business

Our engineers build systems that scale. Clean architecture, comprehensive testing, and security-first development.