How do I squash my last N commits together into a single commit in Git?
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?
- The Interactive Rebase Method
- Step-by-Step Squashing Process
- Alternative Methods for Squashing Commits
- Best Practices and Considerations
- Troubleshooting Common Issues
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:
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 commitsgit 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:
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:
git rebase -i HEAD~N
For example, to squash the last 3 commits:
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
Escto enter command mode - Type
:wqand 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:
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:
# 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:
- Running
git rebase -i HEAD~N - Keeping “pick” for commits you want to preserve
- Changing to “squash” for commits you want to combine
- 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
- Backup your work: Always commit or stash changes before rebasing
- Use branches: Create a new branch before major rewrites
- Test thoroughly: Ensure your code still works after squashing
- 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:
- Resolve the conflicts in your files
- Stage the resolved files:
git add <file> - Continue the rebase:
git rebase --continue - If needed, abort:
git rebase --abort
Editor Issues
If you’re not comfortable with Vim (the default editor), change your default editor:
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:
- Abort the rebase:
git rebase --abort - Restore from your backup stash if needed
Pushing After Squashing
After squashing commits that were previously pushed:
# 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
- Stack Overflow - How do I squash my last N commits together?
- Git Tower - How to Squash Commits in Git
- FreeCodeCamp - Git Squash Commits – Squashing the Last N Commits into One Commit
- Graphite.dev - How to squash Git commits
- Better Stack Community - How Do I Squash My Last N Commits Together?
- Flexiple - Git Squash Commits - Squashing the Last N Commits into One Commit
- Baeldung on Ops - Squash the Last X Commits Using Git
- Garry Trinder - Squash your commits using git interactive rebase
- ThoughtBot - Git interactive rebase, squash, amend and other ways of rewriting history
- DevTutorial - How to squash commits using an interactive rebase