How can I squash my last X commits together into one commit using Git?
I recommend avoiding git reset
when possible -- especially for Git-novices. Unless you really need to automate a process based on a number of commits, there is a less exotic way...
git merge --squash (working branch name)
git commit
The commit message will be prepopulated based on the squash.
Based on this article I found this method easier for my usecase.
My 'dev' branch was ahead of 'origin/dev' by 96 commits (so these commits were not pushed to the remote yet).
I wanted to squash these commits into one before pushing the change. I prefere to reset the branch to the state of 'origin/dev' (this will leave all changes from the 96 commits unstaged) and then commit the changes at once:
git reset origin/dev
git add --all
git commit -m 'my commit message'
2020 Simple solution without rebase :
git reset --soft HEAD~2
git commit -m "new commit message"
git push -f
2 means the last two commits will be squashed. You can replace it by any number
In the branch you would like to combine the commits on, run:
git rebase -i HEAD~(n number of commits back to review)
example:
git rebase -i HEAD~1
This will open the text editor and you must switch the 'pick' in front of each commit with 'squash' if you would like these commits to be merged together. From documentation:
For example, if you are looking to merge all the commits into one, the 'pick' is the first commit you made and all future ones (placed below the first) should be set to 'squash'. If using vim, use :x in insert mode to save and exit the editor.
Then to continue the rebase:
git rebase --continue
For more on this and other ways to rewrite your commit history see this helpful post
If you don't care about the commit messages of the in-between commits, you can use
git reset --mixed <commit-hash-into-which-you-want-to-squash>
git commit -a --amend
In addition to other excellent answers, I'd like to add how git rebase -i
always confuses me with the commit order - older to newer one or vice versa? So this is my workflow:
git rebase -i HEAD~[N]
, where N is the number of commits I want to join, starting from the most recent one. So git rebase -i HEAD~5
would mean "squash the last 5 commits into a new one";Sources & additional reads: #1, #2.