2

I am reading about the pros and cons of squashing commits in Git before crafting a pull request. What I did not find information about is, whether a pull request with squashed commits is more or less likely to turn into a merge conflict if other pull requests are merged into the master while the pull request in question is postponed. I can imagine different scenarios:

  • With a lot of small commits, merge tools can tell easier how things belong together and merge conflicts are less likely. A “merge conflict” can be “resolved” into smaller units, which do not conflict, if considered one by one.
  • With a lot of small commits, merge tools can consider an intermediate commit unmergable already even if a later commit would fix it. (Feels a bit odd.)
  • Technically, it does not make any difference, because the merge tools only look at the last commit anyway.

Which thereof is true, or is the thing even more complicated? (Like, depending on the kind of change?)

amphetamachine
  • 27,620
  • 12
  • 60
  • 72
Matthias Ronge
  • 9,403
  • 7
  • 47
  • 63

2 Answers2

3

If your concern is about running git merge, be aware that git merge locates three commits:

  • your current commit, which is always instantly findable by the name HEAD;
  • your merge target --theirs / other / "remote" commit, which is the one you name when you run git merge otherbranch; and
  • the merge base, which Git locates using the commit graph.

I like to call these three commits L (for Left/Local/--ours), R (for Right/Remote/--theiRs); and B (for base).

If you're squashing "sensibly" (sorry, this is poorly defined!), this has no effect on merge-base-finding. L and B will be the same. The only effect is that R will have a different hash ID. The tree (saved source snapshot) for R will be the same whether or not you have squashed.

git merge effectively does:

git diff --find-renames B L > /tmp/ours.patch
git diff --find-renames B R > /tmp/theirs.patch

and then combines the patches so as to apply the combined-set to the tree in commit B. Since the three trees will be unchanged, squashing will have no effect at all on the merge.

torek
  • 448,244
  • 59
  • 642
  • 775
0

I can think of at least one instance in which a squashed commit would be less likely to result in a conflict:

Say you have three two commits in your branch, A and B, A being the ancestor of B.

With A, it changes five lines near the top of the file, and five lines near the bottom. B does the opposite of the first hunk of A, changing that section of the file back to what it was in A~1.

The total change of A + B is five changed lines near the bottom of the file.

If someone changes something near the five lines at the top of the file, the branch would have a conflict while merging.

If you combined A and B into a new commit C, there would be no conflict.

amphetamachine
  • 27,620
  • 12
  • 60
  • 72
  • `git merge` doesn't look at intermediate commits (although I sometimes think it should, at least for rename detection). You can of course do this yourself, and there's `git-imerge` that does this; for those cases, you're correct. – torek Feb 14 '18 at 00:06