39

I'm trying to use the git merge --squash with the --no-ff parameter, but git does not allow. Someone have any sugestion to help me?

I can't use fast forward merge and I need to use the --squash parameter to group a lot of commits that were made in another branch.

Thanks!

Guilherme Chiara
  • 1,154
  • 2
  • 12
  • 15

4 Answers4

40

It probably doesn't let you because such a command wouldn't make sense.

The documentation for --squash says (emphasis mine):

--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).

The --no-ff flag does:

Create a merge commit even when the merge resolves as a fast-forward.

You are essentially asking git to make a commit and NOT make a commit at the same time.

If you want to preserve all of the history of your branch, you should use the --no-ff flag. Commit d is a merge commit that has two parents, a and c.

a ------ d -- ....
 \      /
  b -- c  

If you want all of the commits on that branch to be treated as a single unit of work, then use --squash. Commit d is a regular commit that contains all of the changes from commits b and c but has only one parent, a.

a ---- d -- ....
 \      
  b -- c  
Mark Ingram
  • 71,849
  • 51
  • 176
  • 230
Roman
  • 19,581
  • 6
  • 68
  • 84
  • Thanks! I've noticed that the squash never commit the changes, it just merge and then "git add" the files that were merge. Is really this or i'm crazy? Sorry for the bad english :( – Guilherme Chiara Jan 14 '13 at 16:37
  • @GuilhermeChiara No, according to the documentation that's how it's supposed to work. Just out of curiosity, why did you change the accepted answer? – Roman Jan 14 '13 at 18:49
  • Thank you for the visual branch diagram patterns. – ilovett May 02 '13 at 16:40
12

What does --squash do? - it squashes all the commits together, creates your index state such that you can commit all the changes from the branch as a single commit. The change in your code will be like you merged the branch, but your history will be like you made one huge commit.

What does --no-ff do? - it says, even if the branch can be fast-forwarded, do treat it as a merge and create a merge commit.

As such, --squash is about getting a history without a trace of merge. --no-ff is about forcing a history with merge, even when it is being forwarded. As such, they are mutually exclusive and cannot be used together.

I think the question arises from a misunderstanding of fast-forward. It is not a merge; it is just about forwarding a branch directly to another commit from the merged branch because the commits were made directly on the commits in the former branch. No fast forward stops this behaviour and forces a merge commit on top. When you are squashing, it doesn't matter if you are asking it to not fast-forward. It would be the same either way.

mouche
  • 1,785
  • 1
  • 16
  • 22
manojlds
  • 290,304
  • 63
  • 469
  • 417
  • 2
    "I think the question arises from a misunderstanding of fast-forward." More likely, it comes from getting the error `fatal: Not possible to fast-forward, aborting.` due to setting `merge.ff` to `only` in .gitconfig, then getting `fatal: You cannot combine --squash with --no-ff.` when trying the `--no-ff` flag. – jpmc26 Jan 12 '16 at 12:04
  • 4
    @jpmc26 I agree :-) That question is tackled [here](http://stackoverflow.com/questions/36486966/how-can-i-squash-merge-when-merge-ff-only). Short answer: do `git -c merge.ff merge --squash ` – Greg Sadetsky Apr 26 '17 at 18:26
  • @GregSadetsky You linked my own question on it. lol! Note that my prior comment precedes the question by several months. – jpmc26 Apr 26 '17 at 20:08
  • Ha! I didn't notice. Cheers :-) – Greg Sadetsky Apr 27 '17 at 23:40
8

This answer is not related to your actual question:

Why can't I use git merge --squash with --no-ff?

as that has been properly answered already.

But rather to make clear that what you were after is indeed possible with a slightly different approach: you would rebase interactive your feature branch first (e.g. to squash all your commits) and after that you could git merge --no-ff the branch on master.

Gera Zenobi
  • 1,344
  • 13
  • 7
3

Review your GIT configuration with the commands:

git config --global -l
git config --local -l

If it contains merge.ff=false, the --no-ff option will be assumed in your git squash commands, causing the problem above. You could remove this option from your configuration with:

git config --global -unset merge.ff
git config --local -unset merge.ff

or directly edit your .gitconfig file.

Rusi Popov
  • 377
  • 1
  • 6