Git: How to squash all commits on branch
I make new branch from master
with:
git checkout -b testbranch
I make 20 commits into it.
Now I want to squash those 20 commits. I do that with:
git rebase -i HEAD~20
What about if I don't know how many commits? Is there any way to do something like:
git rebase -i all on this branch
Solution 1:
Another way to squash all your commits is to reset the index to master:
git checkout yourBranch
git reset $(git merge-base master $(git branch --show-current))
git add -A
git commit -m "one commit on yourBranch"
This isn't perfect as it implies you know from which branch "yourBranch" is coming from.
Note: finding that origin branch isn't easy/possible with Git (the visual way is often the easiest, as seen here).
Note: git branch --show-current
has been introduced with Git 2.22 (Q1 20219).
EDIT: you will need to use git push --force
Karlotcha Hoa adds in the comments:
For the reset, you can do
git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))
[That] automatically uses the branch you are currently on.
And if you use that, you can also use an alias, as the command doesn't rely on the branch name.
Solution 2:
Checkout the branch for which you would like to squash all the commits into one commit. Let's say it's called feature_branch
.
git checkout feature_branch
Step 1:
Do a soft reset of your origin/feature_branch
with your local main
branch (depending on your needs, you can reset with origin/main as well). This will reset all the extra commits in your feature_branch
, but without changing any of your file changes locally.
git reset --soft main
Step 2:
Add all of the changes in your git repo directory, to the new commit that is going to be created. And commit the same with a message.
# Add files for the commit.
git add ...
git commit -m "commit message goes here"
Solution 3:
What you're doing is pretty error-prone. Just do:
git rebase -i master
which will automatically rebase only your branch's commits onto the current latest master.
Solution 4:
Another simple way to do this: go on the origin branch and do a merge --squash
. This command doesn't do the "squashed" commit. when you do it, all commit messages of yourBranch will be gathered.
$ git checkout master
$ git merge --squash yourBranch
$ git commit # all commit messages of yourBranch in one, really useful
> [status 5007e77] Squashed commit of the following: ...
Solution 5:
Assuming you were branching from the master, you don't need to enter yourBranch
into the reset step all the time:
git checkout yourBranch
git reset --soft HEAD~$(git rev-list --count HEAD ^master)
git add -A
git commit -m "one commit on yourBranch"
Explanation:
-
git rev-list --count HEAD ^master
counts the commits since you made your feature branch from the master, f.ex. 20. -
git reset --soft HEAD~20
will make a soft reset of the last 20 commits. This leaves your changes in the files, but removes the commits.
Usage:
In my .bash_profile I have added an alias for gisquash
to do this with one command:
# squash all commits into one
alias gisquash='git reset --soft HEAD~$(git rev-list --count HEAD ^master)'
After reseting and committing you need to do a git push --force
.
Hint:
If you're using Gitlab >= 11.0 you don't need to do this anymore as it has a squashing option when merging branches.