Git: Why Squashing Can Result in Conflicts in Other Branches

## TLDR: Even With Only 1 Commit, Squash-Merging is Fundamentally Different!
 When squash-merging in git, _even if the source branch only has one commit_, then the result is still drastically **different** to a "regular" merge that creates a merge commit.

In particular, if the source branch has any child branches that will _also be merged_ into the _same target_ later on, a squash merge may cause **conflicts** in those later merges.

#### Also Useful Pre-requisite Knowledge
Also, conflicts occur during a merge when:
- With respect to the _nearest common ancestor_ of the _source_ and _target_:
- source and target make different changes to the same line

## 

The other day, when merging a PR and choosing between the "Squash and merge" and "Create a merge commit", a comment from a co-worker exposed a big hole in my git-understanding. 

## The situation
 The source branch which I wanted to merge into the target, had its own child branch,
which would **also eventually have to be merged into the target**. 

Or put more visually:

```
main --> 
        child -->             # 親=main,  1 commit
                  grandchild  # 親=child, 1 commit, OVERWRITES CHANGES IN CHILD
```

- I was trying to merge `child` into `main`
- At a later point, `grandchild` would also need merging into `main`

### The comment:
> You should do a regular merge instead of a squash merge, otherwise We'll probably **get a conflict later on when merging granchild**


### My foolish response:
> child only has 1 commit, so wouldn't a squash be the same as a regular merge? And why would a squash cause a conflict at grandchild's merge?

### To which my learned co-worker replied
> Even if there's only one commit in the source, **a squash merge is completely different to a regular merge**, if you look at the log graph you'll see the history is different.

I was confused by this reply, and knew I it was time to go back to git-school. 
Here are the main points that I newly understood as a result:

## What Happens in a "Squash & Merge"?
- A new commit is added to the target branch
- The history of source is not preserved in this commit - it only has one parent in the target branch
  - When you look at the log graph for the target branch, its just a single line

## What Happens in a Regular Merge? ("Create a merge commit")
- Similary to squash and merge, a single commit is added to the target branch
- However, the **source history is preserved**, and it has two parent commits - because it's a **merge-commit**
  - when you look at the log graph for the target branch, you see two lines converging, with **separate commits remaining on the source, and target branches**

## Wait, When do Merge Conflicts Occur Exactly?
A merge consists of
- base/common ancestor
- target (merge into)
- source (merge from)

A conflict occurs when, with _respect to the base_, target and source contain **different changes to the same line**.

### Example of Regular Merge: No Conflict at Grandchild Merge
First, if child is merged into main, creating a merge commit, you get the "after" situation:
![スクリーンショット 2025-03-03 12.13.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1680534/70d84661-3a60-49d7-a0f7-fbce8955ff51.png)


This means, when it comes to merging `grandchild` into `main`:
- base/common-ancestor is B
- target: D (merge commit created when merging child into main)
- source: C

Since a merge commit doesn't contain any changes, there are no changes for the source's changes to conflict with!
  → **no conflict!**


### Example of Squash-Merge: Conflict at Grandchild Merge!
First, if child is squash-merged into main, you get the "after" situation:

![スクリーンショット 2025-03-03 12.32.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1680534/42ebf8db-b56e-4523-a246-0750d6f65c3e.png)


This means, when it comes to merging `grandchild` into `main`:
- base/common-ancestor is all the way back in A
- target: D (commit created when squash-merging child into main)
- source: C

Since source and target now contain conflicting changed with respect to A, you get a conflict!
  → **conflict!**

## Summary

Squash merging a branch that has a child branch into main, means that when the child's nearest common ancestor with main will be further back.
Which means there is a much greate chance of a merge conflict!

On the otherhand, creating a merge commit keeps that child's nearest common ancestor very recent, reducing the chance of a merge conflict.