Another way to squash all your commits is to reset the index to main
:
(Reminder: Note: since Git 2.28 (Q3 2020), the default branch is configurable, and now (2021+) set to main
, no longer master
.)
If you need the following commands to work for any default branch, replace main
with ${defaultBranch}
.
And define defaultBranch=$(git config --get init.defaultBranch || echo master)
.
For Git previous to 2.28, defaultBranch
will be set to master
.
For for recent Git versions, it will be main
.
Back to the solution: (to squash all your commit) reset the index to main
:
git checkout yourBranch
git reset $(git merge-base main $(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 (Q2 2019).
Or, as noted by Hiroki Osame in the comments:
git switch yourBranch
git reset --soft $(git merge-base main HEAD)
git commit -m "one commit on yourBranch"
- no need for
git branch --show-current
since HEAD is already a reference to that branch. - no need for
git add -A
, sincegit reset --soft
only moves HEAD, and leaves the index untouched (in other words, the files are already “added”).
EDIT: you will need to use git push --force
(or git push --force-with-lease
)
See “git push --force-with-lease
vs. --force
“
Karlotcha Hoa adds in the comments:
For the reset, you can do
git reset $(git merge-base main $(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.