Could anyone please tell me what the difference between these two commands:
git merge --squash
and
git merge --no-ff
You should consider using squash if your team prefers a linear project history. This means that the history held by your main branch should not contain merges. A squash merge makes it possible to keep changes condensed to a single commit, supporting this strategy nicely.
To enable commit squashing as the default option in your repository: Navigate to your chosen repository and open the Settings sub-tab. Open the General Settings page. Check the box for Squash commits on merge default enabled.
What does it mean to squash commits in Git? Squashing is a way to rewrite your commit history; this action helps to clean up and simplify your commit history before sharing your work with team members. Squashing a commit in Git means that you are taking the changes from one commit and adding them to the Parent Commit.
I think your question indicates a bit of a misunderstanding. --no-ff
and --squash
are not opposites, rather they are subtly different operations. Keep that in mind while reading.
The help page for merge says the following about --squash
:
--squash
and--no-squash
Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit or move the HEAD, nor record $GIT_DIR/MERGE_HEAD to cause the next git commit command to create a merge commit. This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).
With --no-squash perform the merge and commit the result. This option can be used to override --squash.
That's a bit confusing, and requires some knowledge about the internals of git
. To start, we need to understand the difference between a regular commit and a merge commit. A regular commit has one parent, and is simply a changeset to apply to the commit before it:
A --> B --> C
A merge commit has multiple parents, and it a place in the tree where you've brought two or more lineages together:
A --> B --> F
/
C --> D - /
See how A
, B
, C
, and D
are regular commits, but F
is a merge commit, since it has multiple parents (B
and D
)? This is what git merge --no-ff
would produce. It forces Git to create a merge commit to bring two histories together.
git merge --squash
would do something a little different. It prevents Git from creating a merge commit, but still pulls in the changes C
and D
made, so your tree looks like this:
A --> B --> F'
C --> D
F'
contains changes C
and D
made, but there's no sign of the fact you merged two trees in the repository.
--no-ff
is a slightly different operation. It forces Git into creating a merge commit even if it's not really necessary. For reference, here's what the manual has to say about --no-ff
and it's opposite --ff-only
:
--no-ff
Create a merge commit even when the merge resolves as a fast-forward.
--ff-only
Refuse to merge and exit with a non-zero status unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward.
To understand, it's best to look at an example:
A --> B --> C --> D --> E
| |
'master' 'topic'
If you had this tree, were on the master branch, and ran git merge
, Git would perform what's called a "fast-forward" merge. Since there's no divergence between the two histories, Git can just move the master
branch up to where topic
sits without doing anything interesting. It would look like this:
A --> B --> C --> D --> E
|
'topic'
'master'
With both topic and master pointing to the same branch. Now, some workflow policies require that you create a merge commit every time you merge back into master
. This keeps the history of branches around. You'll get arguments either way on how it should be done, but I won't get into those here.
If you used git merge --no-ff
on that same tree instead, it would force git to create a merge commit, giving you a tree like this:
'master'
|
A --> B -------------> F
\ /
C --> D --> E
|
'topic'
Where F
is the new merge commit --no-ff
force Git to create.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With