GitHub에서 Pull Request(PR)를 병합할 때 사용할 수 있는 세 가지 방법
1. Merge Commit (새로운 병합 커밋 생성)
일반적으로 git merge <branch-name> 명령어를 실행할 때 기본적으로 사용되는 방법이다.
1) 작동 방식
Merge Commit 생성: 두 브랜치(main과 feature)의 변경 이력을 합치고, 그 결과를 저장하는 새로운 커밋(Merge Commit)을 대상 브랜치에 만든다.
Non-Fast-Forward: 대상 브랜치(main)가 병합하려는 브랜치(feature)의 공통 조상 커밋 이후로 발전된 커밋을 가지고 있을 때 발생한다.
이력 보존: feature 브랜치의 모든 커밋과 브랜치 분기 이력 자체가 그대로 유지된다.
2) 이력 형태 (비선형)
main과 feature 브랜치가 각자의 길을 걸은 후 합쳐지는 형태이다.
결과: 다이아몬드 또는 Y자 형태의 그래프가 만들어진다.
특징: 브랜치가 언제 시작되었고, 언제 다시 합쳐졌는지 시각적으로 명확하게 알 수 있다.
1
2
3
* --- * --- C4 (Merge Commit) <-- main
\ /
C1 --- C2 --- C3 <-- feature
3) 장점
추적 용이성: 브랜치 작업의 시작과 끝을 명확히 알 수 있어, 나중에 문제가 생겼을 때 작업 단위를 통째로 되돌리기(Revert)가 가장 쉽다.
안정성: 핵심 브랜치(prod 또는 stg)의 병합 기록을 정확하게 남겨야 할 때 가장 적합하다.
4) 단점
- 병합 커밋이 반복적으로 생성되어 커밋 이력이 복잡해지고 지저분해 보일 수 있다.
2. Rebase and Merge (Rebase 후 Fast-Forward)
GitHub의 Rebase and Merge 옵션이 수행하는 방식이며, 이력을 선형으로 깨끗하게 만들 때 유용하다.
1) 작동 방식
커밋 재배치: 병합하려는 브랜치(feature)의 커밋들을 대상 브랜치(main)의 최신 커밋 위로 ‘옮겨 심는다’(Rebase).
이력 재작성: 이 과정에서 feature 브랜치에 있던 모든 커밋의 해시(ID)가 새롭게 재작성된다.
Fast-Forward Merge: 재배치된 커밋들만 남아있으므로, main 브랜치는 포인터를 단순히 최신 커밋으로 이동시키는 Fast-Forward 방식을 사용하여 병합을 완료한다. 별도의 Merge Commit은 생성되지 않는다.
2) 이력 형태 (선형)
feature 브랜치가 마치 main의 최신 상태에서부터 작업한 것처럼 보인다.
- 결과: 완벽하게 일자형(선형) 형태의 그래프가 된다. 브랜치가 분기되었던 기록은 사라진다.
1
2
3
* --- * --- C1' --- C2' --- C3' <-- main/feature
(C1, C2, C3이 재작성되어 C1', C2', C3'이 된다)
3) 장점
가독성: 커밋 이력이 매우 깔끔하고, 복잡한 Merge Commit이 없어 이력을 훑어보기 좋다.
Fast-Forward: Merge Commit이 없기 때문에, 커밋 메시지 검색 등에서 유리할 수 있다.
4) 단점
이력 재작성: 커밋 해시가 바뀌기 때문에, 이미 외부에 공유된 브랜치에 사용하면 협업에 문제가 생길 수 있다.
복잡한 Conflict: 병합 시 Conflict가 발생하면, rebase하는 모든 커밋마다 충돌을 해결해야 할 수 있다.
5) 주의
- History Rewriting: rebase는 커밋 해시를 바꾸기 때문에, 이미 공유된(Push된) 공용 브랜치에는 절대 사용해서는 안 된다. (GitHub PR에서는 서버가 이 과정을 안전하게 처리해준다.)
3. Squash and Merge (압축 병합)
수많은 작은 커밋들을 하나의 의미 있는 단위로 통합하여 병합하고 싶을 때 사용한다.
1) 작동 방식
커밋 압축: feature 브랜치에 있는 모든 커밋(예: “WIP”, “테스트”, “오타 수정”)을 하나의 거대한 커밋으로 합친다.
단일 커밋 생성: 이 압축된 단일 커밋을 대상 브랜치(main)에 Merge Commit 없이 추가한다.
이력 소멸: feature 브랜치 자체는 여전히 로컬에 원래의 상세한 커밋들을 가지고 있지만, main 브랜치에는 오직 압축된 커밋 하나만 남는다.
2) 이력 형태 (선형)
- 결과: 이력은 선형으로 보이지만, 브랜치 작업의 모든 과정은 하나의 큰 덩어리 커밋으로 대체된다.
1
2
* --- * --- C_SQUASHED <-- main
(C_SQUASHED는 C1, C2, C3의 모든 변경 사항을 담고 있다.)
3) 장점
간결한 이력: “하나의 Pull Request = 하나의 커밋”이라는 원칙을 적용할 수 있어, 이력이 기능 단위로 명확하게 정리된다.
롤백 단순화: 기능 전체를 되돌리고 싶을 때, 단 하나의 커밋만 되돌리면 되므로 관리가 매우 간단하다.
4) 단점
- 상세 이력 손실: 피처 브랜치에서 작업했던 상세한 과정(C1, C2, C3)을 알 수 없다.