충돌이 없는데도 Merge 커밋이 생기는 이유, 3-way Merge 알고리즘, 그리고 복잡해진 Git 그래프를 정리하는 전략까지.
어떤 때는 Merge가 커밋 없이 조용히 끝나고, 어떤 때는 Merge Commit이 하나 생겨납니다. 충돌도 없는데 커밋이 생기는 게 히스토리를 지저분하게 만드는 느낌이 들기도 합니다.
“모든 Merge가 커밋을 만드는 건 아니다. 그렇다면 어떤 조건에서 커밋이 생기는가?
이를 이해하려면 Git이 데이터를 관리하는 구조인 DAG(Directed Acyclic Graph)와 3-way Merge 알고리즘을 살펴봐야 합니다.
Git에서 모든 Merge가 커밋을 생성하지는 않습니다. 커밋 히스토리가 한 줄로 이어질 수 있는 상황이라면 브랜치 포인터만 앞으로 이동시킵니다. 이를 Fast-Forward라고 합니다.
Fast-Forward (커밋 없음)
main: A → B
feature: → C → D
머지 결과: main이 D를 가리키도록 포인터만 이동
A → B → C → D (선형 유지)
Merge 커밋이 생기는 상황은 두 가지입니다.
--no-ff 옵션으로 Fast-Forward 가능한 상황에서도 명시적으로 머지 커밋을 남기고자 할 때Merge 커밋이 생기는 경우
main: A → B → C
feature: ↘ D → E
공통 조상 B 이후 두 브랜치가 갈라짐 → Merge 커밋 M 생성
A → B → C → M
↗
D → E
Merge 커밋을 생성할 때 Git은 단순히 두 브랜치의 끝만 비교하지 않습니다. 세 가지 지점을 참조합니다.
두 브랜치의 최신 커밋만 비교(2-way)하면 어떤 쪽이 "원래 상태"이고 어떤 쪽이 "변경한 것"인지 알 수 없습니다. 공통 조상을 기준점으로 삼아야 각 브랜치가 무엇을 의도적으로 바꿨는지 정확히 파악할 수 있습니다.
Git은 공통 조상 대비 각 브랜치에서 어떤 변경이 있었는지 줄 단위로 비교합니다.
| 상황 | 결과 |
|---|---|
| 조상 대비 Branch 1만 변경 | Branch 1의 내용 채택 |
| 조상 대비 Branch 2만 변경 | Branch 2의 내용 채택 |
| 두 브랜치 모두 같은 내용으로 변경 | 해당 내용 채택 |
| 두 브랜치가 같은 부분을 다르게 수정 | Conflict — 사용자 개입 필요 |
이 비교 과정을 통해 Git은 모든 변경사항을 통합한 새로운 스냅샷을 만듭니다.
일반 커밋은 바로 이전 커밋 하나만을 부모로 갖습니다. Merge 커밋의 가장 큰 특징은 부모가 2개 이상이라는 점입니다.
일반 커밋: A ← B ← C
↑
parent: 1개
Merge 커밋: A ← B ← C ← M
↑ ↑
D ← E ←───────┘
parent: 2개 (C, E)
tree 객체로 기록합니다.revert하면 해당 기능 전체를 되돌릴 수 있음git bisect로 버그를 찾을 때 노드가 많아 특정이 까다로워짐 - 역방향 머지가 반복되면 그래프가 급격히 복잡해짐Merge 커밋이 누적되면 아래와 같은 "기찻길 현상"이 생깁니다.

이 현상은 단순히 머지를 많이 해서가 아니라, 비선형 히스토리 관리 전략이 반복될 때 나타납니다.
왜 이런 형태가 만들어지는가
develop → release/prod 방향으로 주기적으로 머지하면 각 시점마다 연결선이 추가됩니다. 여기에 release/prod → develop 역방향 머지까지 섞이면 선들이 서로 꼬이기 시작합니다.--no-ff를 사용하면 불필요한 머지 커밋이 계속 쌓입니다.git bisect로 버그 커밋을 찾을 때 머지 노드가 많으면 이진 탐색이 꼬입니다.내 브랜치의 변경사항을 대상 브랜치의 최신 커밋 위로 재배치합니다.
git checkout feature
git rebase main
git checkout main
git merge feature # 이제 Fast-Forward 가능
Before: A → B → C (main)
↘ D → E (feature)
After: A → B → C → D' → E' (선형 유지)
main, develop 같이 다른 사람과 공유하는 브랜치에서는 Rebase를 사용하지 않습니다.
혼자 작업하는 feature 브랜치에서만 사용하는 것이 안전합니다.
팀의 워크플로우와 브랜치 전략에 따라 다릅니다.
--no-ff 일관 적용