Search code examples
gitversion-controlsquashgit-squash

Does squashing commits have an impact on mergability?


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


Solution

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