NeuroAgent

How to Squash Last N Git Commits: Complete Guide

Learn how to squash your last N Git commits into one clean commit using interactive rebase. Step-by-step tutorial with best practices and troubleshooting tips.

Question

How do I squash my last N commits together into a single commit in Git?

NeuroAgent

To squash your last N commits together into a single commit in Git, use the interactive rebase command git rebase -i HEAD~N where N is the number of commits you want to combine. This will open an editor where you can change “pick” to “squash” for the commits you want to merge, then save and edit the new commit message. The process rewrites your commit history by combining multiple commits into one, creating a cleaner and more organized repository history.


Contents


What is Commit Squashing in Git?

Commit squashing is the process of combining multiple commits into a single commit in Git. This technique allows you to consolidate several smaller commits into one logical unit, resulting in a cleaner and more readable commit history. As Git Tower explains, “To ‘squash’ in Git means to combine multiple commits into one. You can do this at any point in time (by using Git’s ‘Interactive Rebase’ feature), though it is most often done when merging branches.”

The primary motivation for squashing commits is to maintain a clean, professional repository history rather than having numerous small commits that might contain debugging work, minor fixes, or incremental changes that don’t contribute to the overall narrative of your work.

Why Squash Commits?

  • Cleaner history: Reduces clutter in your commit log
  • Better readability: Makes it easier for others to understand the evolution of your code
  • Professional presentation: Creates a more polished repository history
  • Simplified merges: Reduces conflicts when merging branches
  • Better code reviews: Makes it easier to review changes in logical chunks

The Interactive Rebase Method

The most common and recommended way to squash commits is using Git’s interactive rebase feature. According to FreeCodeCamp, “In this process, you will grab all the commits with the git rebase command with the i flag and put them together with squash.”

The basic command structure is:

bash
git rebase -i HEAD~N

Where N is the number of commits you want to include in the squashing process. For example:

  • git rebase -i HEAD~3 - Squashes the last 3 commits
  • git rebase -i HEAD~5 - Squashes the last 5 commits

When you run this command, Git opens your default editor (usually Vim) with a list of the commits you’ve specified, showing the commit hashes and messages. Each commit is prefixed with the word “pick”, which means “keep this commit as is.”


Step-by-Step Squashing Process

Step 1: Check Your Current Commit History

Before squashing, review your recent commits to understand what you’re working with:

bash
git log --oneline -N

Replace N with the number of commits you plan to squash. This helps you identify which commits to combine.

Step 2: Start Interactive Rebase

Run the interactive rebase command for your desired number of commits:

bash
git rebase -i HEAD~N

For example, to squash the last 3 commits:

bash
git rebase -i HEAD~3

Step 3: Edit the Rebase File

The editor will open with content similar to this:

pick 1171930 Add test step
pick f87e360 Implement artifact uploading
pick 31908ef Add environment-specific deployments

To squash commits, change “pick” to “squash” (or just “s”) for the commits you want to merge into the first one. The first commit should remain “pick” as it will be the one that absorbs the others:

pick 1171930 Add test step
squash f87e360 Implement artifact uploading
squash 31908ef Add environment-specific deployments

Step 4: Save and Close the Editor

Save the file and close the editor. In Vim, you would:

  • Press Esc to enter command mode
  • Type :wq and press Enter

Step 5: Edit the Commit Message

Git will now open another editor with a combined commit message. You can edit this to create a meaningful message that describes all the changes:

# This is a combination of 3 commits.
# The first commit's message is:
Add test step

# This is the 2nd commit's message:
Implement artifact uploading

# This is the 3rd commit's message:
Add environment-specific deployments

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

Step 6: Finalize the Squash

Save and close the editor again. Git will now create a single commit containing all the changes from the squashed commits.

Step 7: Verify the Result

Check your commit history to confirm the squash was successful:

bash
git log --oneline -5

You should now see one commit instead of the original N commits.


Alternative Methods for Squashing Commits

Method 2: Using git reset (for local commits only)

If you haven’t pushed your commits to a remote repository yet, you can use git reset to squash commits:

bash
# Reset N commits back, keeping changes staged
git reset --soft HEAD~N

# Commit the staged changes with a new message
git commit -m "Your new commit message"

This approach is mentioned by DesignGurus as an alternative method: “This moves HEAD back by two commits, keeping the changes staged. The last two commits are now merged into a single commit.”

Method 3: Using GUI Tools

Many Git GUI tools provide visual interfaces for squashing commits:

  • GitHub Desktop: Has built-in interactive rebase support
  • SourceTree: Offers visual commit management and squashing
  • IntelliJ IDEA: As shown in this YouTube video, provides interactive rebase features

Method 4: Partial Squashing with Interactive Rebase

Sometimes you don’t want to squash all N commits. You can selectively squash by:

  1. Running git rebase -i HEAD~N
  2. Keeping “pick” for commits you want to preserve
  3. Changing to “squash” for commits you want to combine
  4. Using “drop” to completely remove commits you don’t need

Best Practices and Considerations

When to Squash Commits

Good candidates for squashing:

  • Feature branches that are about to be merged
  • Multiple small commits that logically belong together
  • Debugging commits that are no longer relevant
  • Work-in-progress commits that were accidentally committed

Avoid squashing:

  • Commits that have already been pushed to shared repositories
  • Commits with collaborators’ work (unless you have permission)
  • Important historical commits that provide context
  • Commits that have been reviewed and approved

Safety Precautions

  1. Backup your work: Always commit or stash changes before rebasing
  2. Use branches: Create a new branch before major rewrites
  3. Test thoroughly: Ensure your code still works after squashing
  4. Communicate with your team: If working on shared repositories, inform collaborators

Branch Protection

If you’re working on team repositories, consider using branch protection rules to prevent force pushes, which can help avoid accidental history rewriting.


Troubleshooting Common Issues

Conflicts During Rebase

If you encounter merge conflicts during interactive rebase:

  1. Resolve the conflicts in your files
  2. Stage the resolved files: git add <file>
  3. Continue the rebase: git rebase --continue
  4. If needed, abort: git rebase --abort

Editor Issues

If you’re not comfortable with Vim (the default editor), change your default editor:

bash
git config --global core.editor "code --wait"  # VS Code
git config --global core.editor "nano"         # Nano
git config --global core.editor "emacs"        # Emacs

Accidental Squashing

If you squash commits by mistake and haven’t pushed them:

  1. Abort the rebase: git rebase --abort
  2. Restore from your backup stash if needed

Pushing After Squashing

After squashing commits that were previously pushed:

bash
# Force push (use with caution!)
git push --force-with-lease origin your-branch

Consider using --force-with-lease instead of --force as it’s safer and prevents you from overwriting others’ work.


Conclusion

Squashing commits is a powerful technique for maintaining clean, readable Git histories. The interactive rebase method (git rebase -i HEAD~N) is the standard approach for combining your last N commits into a single, well-documented commit. Remember to always backup your work before rewriting history and communicate with your team when working on shared repositories.

By following the step-by-step process outlined above and understanding the best practices, you can effectively manage your commit history and keep your repository organized and professional. Whether you’re working on personal projects or team collaborations, commit squashing will help you present your work in the best possible light.

For more advanced Git history management, consider exploring other interactive rebase commands like reword, edit, and drop to further customize your commit history.


Sources

  1. Stack Overflow - How do I squash my last N commits together?
  2. Git Tower - How to Squash Commits in Git
  3. FreeCodeCamp - Git Squash Commits – Squashing the Last N Commits into One Commit
  4. Graphite.dev - How to squash Git commits
  5. Better Stack Community - How Do I Squash My Last N Commits Together?
  6. Flexiple - Git Squash Commits - Squashing the Last N Commits into One Commit
  7. Baeldung on Ops - Squash the Last X Commits Using Git
  8. Garry Trinder - Squash your commits using git interactive rebase
  9. ThoughtBot - Git interactive rebase, squash, amend and other ways of rewriting history
  10. DevTutorial - How to squash commits using an interactive rebase