How can I squash my last X commits together into one commit using Git?
Based on Chris Johnsen's answer,
Add a global "squash" alias from bash: (or Git Bash on Windows)
git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
... or using Windows' Command Prompt:
git config --global alias.squash "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Your ~/.gitconfig
should now contain this alias:
[alias]
squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Usage:
git squash N
... Which automatically squashes together the last N
commits, inclusive.
Note: The resultant commit message is a combination of all the squashed commits, in order. If you are unhappy with that, you can always git commit --amend
to modify it manually. (Or, edit the alias to match your tastes.)
Use git rebase -i <after-this-commit>
and replace "pick" on the second and subsequent commits with "squash" or "fixup", as described in the manual.
In this example, <after-this-commit>
is either the SHA1 hash or the relative location from the HEAD of the current branch from which commits are analyzed for the rebase command. For example, if the user wishes to view 5 commits from the current HEAD in the past the command is git rebase -i HEAD~5
.
To do this you can use following git command.
git rebase -i HEAD~n
n(=4 here) is the number of last commit. Then you got following options,
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
Update like below pick
one commit and squash
the others into the most recent,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
For details click on the Link
1) Identify the commit short hash
# git log --pretty=oneline --abbrev-commit
abcd1234 Update to Fix for issue B
cdababcd Fix issue B
deab3412 Fix issue A
....
Here even git log --oneline
also can be used to get short hash.
2) If you want to squash (merge) last two commit
# git rebase -i deab3412
3) This opens up a nano
editor for merging. And it looks like below
....
pick cdababcd Fix issue B
pick abcd1234 Update to Fix for issue B
....
4) Rename the word pick
to squash
which is present before abcd1234
. After rename it should be like below.
....
pick cdababcd Fix issue B
squash abcd1234 Update to Fix for issue B
....
5) Now save and close the nano
editor. Press ctrl + o
and press Enter
to save. And then press ctrl + x
to exit the editor.
6) Then nano
editor again opens for updating comments, if necessary update it.
7) Now its squashed successfully, you can verify it by checking logs.
# git log --pretty=oneline --abbrev-commit
1122abcd Fix issue B
deab3412 Fix issue A
....
8) Now push to repo. Note to add +
sign before the branch name. This means forced push.
# git push origin +master
Note : This is based on using git on ubuntu
shell. If you are using different os (Windows
or Mac
) then above commands are same except editor. You might get different editor.
git add <files>
--fixup
option and the OLDCOMMIT
should be on which we need to merge(squash) this commit.git commit --fixup=OLDCOMMIT
Now this creates a new commit on top of HEAD with fixup1 <OLDCOMMIT_MSG>
.
OLDCOMMIT
.git rebase --interactive --autosquash OLDCOMMIT^
Here ^
means the previous commit to OLDCOMMIT
. This rebase
command opens interactive window on a editor (vim or nano) on that
we no need to do anything just save and exiting is sufficient. Because the option passed to this will automatically move the latest
commit to next to old commit and change the operation to fixup
(equivalent to squash). Then rebase continues and finishes.
--amend
can be used with git-commit
. # git log --pretty=oneline --abbrev-commit
cdababcd Fix issue B
deab3412 Fix issue A
....
# git add <files> # New changes
# git commit --amend
# git log --pretty=oneline --abbrev-commit
1d4ab2e1 Fix issue B
deab3412 Fix issue A
....
Here --amend
merges the new changes to last commit cdababcd
and generates new commit ID 1d4ab2e1
If for example, you want to squash the last 3 commits to a single commit in a branch (remote repository) in for example: https://bitbucket.org
What I did is
git reset --soft HEAD~3
git commit
git push origin <branch_name> --force
To squash the last 10 commits into 1 single commit:
git reset --soft HEAD~10 && git commit -m "squashed commit"
If you also want to update the remote branch with the squashed commit:
git push -f