4

I've working with a small team using the 'merge workflow' and we recently switched over to the 'rebase workflow' as per Sandofsky's article.

our current workflow:

  1. git checkout master, git pull origin master
  2. git checkout -b feature_branch, do some work and git commit -am "msg for feature branch"
  3. git checkout master, git pull origin master, git rebase master feature_branch
  4. git checkout master, git merge --squash
  5. git commit -am "msg for master branch", git push origin master

After rebasing the feature branch, we squash merge it into our master. What would happen if we used --no-ff instead? What is the difference between git merge --squash and git merge --no-ff?

Nikola
  • 817
  • 13
  • 19
  • See http://stackoverflow.com/q/11983749/1885037 for a good explanation. – kaveish Jul 06 '16 at 09:17
  • Possible duplicate of [What are the differences between \`--squash\` and \`--no-ff --no-commit\`?](https://stackoverflow.com/questions/11983749/what-are-the-differences-between-squash-and-no-ff-no-commit) – rds Jun 05 '17 at 21:24

3 Answers3

5

--squash creates a single commit with all the merge's changes (it squashes the entire merged branch's history into one commit). --no-ff also merges in a branch, creating a merge commit and retaining the entire history of the merged branch.

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • @JohnLittle: Only `--squash` yields a single commit, discarding any commits made on the branch being merged, and it does _not_ create a merge commit; `--no-ff` creates a merge commit and retains the entire history (i.e., all of the commits) of the branch being merged. – mipadi Jan 14 '22 at 18:29
4

git merge --squash creates a single commit that applies all the changes you would apply with a normal merge. So, it melds all the commits you would bring to the branch in a single commit.

git merge --no-ff prevents fast-forwards - the operation of just moving the branch pointer to a newer commit if the source and target haven't diverged. So, using --no-ff you guarantee you'll have a new commit whose parents will be your current HEAD and the feature_branch head.

When you log both scenarios, in the first one you'll just see a single line of commits, each one being a feature_branch digest, while in the second one you'll see lots of ramifications, one for each feature_branch, and all joining master again.

As git merge --squash generates a new commit based on the feature_branch ones, they are different commits, so you can have trouble if you published feature_branch alone - say, you can git merge --squash feature_branch multiple times without git understanding it, but you'll have conflicts.

mgarciaisaia
  • 14,521
  • 8
  • 57
  • 81
  • 1
    Which should be used to merge a PR into its parent? Both seem to generate a single commit representing all commits of the feature branch - I cant see the difference. Devops Git PR merge only offers merge --squash. Most git-flow blogs use -no-ff. Why does devops git not offer both, if -no-ff is better? – John Little Jan 13 '22 at 07:56
1

The biggest difference is going to be in your branch history. With --squash, you will have a linear branch history where each commit on the branch contains all of the changes that the merge for that commit performed. With --no-ff, you will have a divergent branch history with merge commits showing where two branches came together with multiple parents, and the parent commits will contain the actual changes made.

Personally, I prefer the --squash method as it makes identifying where a change came from easier (because the change is in the actual squashed commit and not a parent commit). The downside is that it is a unique commit and not a commit history, so if you continue to develop on that branch and do another squash commit, you will get another commit that contains the entire history of changes for that branch. This can make identifying where a change came from more difficult, because it can appear that the same change was made in two different commits. The solution to this is to delete the branch after you do a squash commit and any changes or improvements should be in a new branch off of develop that contains the squash commit in its history.

Zaratuir
  • 11
  • 1