I'm new to git and I'm trying to understand the difference between a squash and a rebase. As I understand it you perform a squash when doing a rebase.
Both git merge --squash
and git rebase --interactive
can produce a "squashed" commit.
But they serve different purposes.
will produce a squashed commit on the destination branch, without marking any merge relationship.
(Note: it does not produce a commit right away: you need an additional git commit -m "squash branch"
)
This is useful if you want to throw away the source branch completely, going from (schema taken from SO question):
git checkout stable
X stable
/
a---b---c---d---e---f---g tmp
to:
git merge --squash tmp
git commit -m "squash tmp"
X-------------------G stable
/
a---b---c---d---e---f---g tmp
and then deleting tmp
branch.
Note: git merge
has a --commit
option, but it cannot be used with --squash
. It was never possible to use --commit
and --squash
together.
Since Git 2.22.1 (Q3 2019), this incompatibility is made explicit:
See commit 1d14d0c (24 May 2019) by Vishal Verma (reloadbrain
).
(Merged by Junio C Hamano -- gitster
-- in commit 33f2790, 25 Jul 2019)
merge
: refuse--commit
with--squash
Previously, when
--squash
was supplied, 'option_commit
' was silently dropped. This could have been surprising to a user who tried to override the no-commit behavior of squash using--commit
explicitly.
git/git
builtin/merge.c#cmd_merge()
now includes:
if (option_commit > 0)
die(_("You cannot combine --squash with --commit."));
replays some or all of your commits on a new base, allowing you to squash (or more recently "fix up", see this SO question), going directly to:
git checkout tmp
git rebase -i stable
stable
X-------------------G tmp
/
a---b
If you choose to squash all commits of tmp
(but, contrary to merge --squash
, you can choose to replay some, and squashing others).
So the differences are:
squash
does not touch your source branch (tmp
here) and creates a single commit where you want.rebase
allows you to go on on the same source branch (still tmp
) with: