[GIT] GIT 병합 전략 - Recursive Merge, Fast-Forward Merge, Squash Merge, Rebase and Merge
A. Question
GIT 병합 전략에는 어떤 것들이 있는가?
B. Answer
1. Fast-Forward Merge
(1) 개념
- Fast-Forward Merge는 병합 대상 브랜치가 직선형 히스토리로 이어질 수 있는 경우 발생한다.
- 병합 시 새로운 병합 커밋이 생성되지 않고, 대상 브랜치의 HEAD가 병합하려는 브랜치의 HEAD로 단순히 이동한다.
(2) 동작 조건
- 공통 조상 이후, 대상 브랜치에 새로운 커밋이 없을 때
- 예:
main
브랜치가C2
에서 멈춘 상태이고,feature
브랜치에만 추가 커밋C4
가 있는 경우
- 예:
- 두 브랜치가 공통 히스토리를 유지하며 분기되지 않은 상태
(3) 예시
-
Before Merge
main: C0 → C1 → C2 feature: → C3
-
After Fast-Forward Merge
main: C0 → C1 → C2 → C3
(4) 명령어
# main 브랜치로 이동
git checkout main
# feature 브랜치를 Fast-Forward 방식으로 병합
git merge feature
(5) 장단점
- 장점
- 히스토리가 단순하고 깔끔하게 유지된다.
- 추가 병합 커밋이 생성되지 않아 로그가 간결하다.
- 단점
- 브랜치 병합 이력이 명확히 표시되지 않아 추적이 어려울 수 있다.
- 변경 내용이 많거나 중요한 경우에는 적합하지 않을 수 있다.
(6) Fast-Forward Merge가 불가능한 경우
- 대상 브랜치
main
에 새로운 커밋이 존재하는 경우 - 두 브랜치
main
과feature
가 공통 조상 이후 각각 독립적으로 변경 사항을 가지는 경우
이 경우 Non-Fast-Forward Merge 또는 Recursive Merge(3-way Merge)가 수행된다.
(7) Fast-Forward Merge를 강제하지 않는 방법
작업 이력을 명확히 구분하고 싶을 때, 롤백이 용이해야 할 때, 혹은 대규모 프로젝트에서 병합 이력이 중요한 경우, Fast-Forward Merge 대신 병합 커밋을 생성하는 것이 유리하다.
-
--no-ff
옵션을 사용하면 Fast-Forward Merge 대신 병합 커밋이 생성된다.git merge --no-ff feature
2. Recursive Merge (3-Way Merge)
(1) 개념
- Recursive Merge는 두 브랜치 간 공통 조상 커밋을 기준으로, 병합하려는 브랜치와 대상 브랜치의 변경 사항을 비교하고 병합하는 방식이다.
- 3-Way Merge라고도 불리며, 두 브랜치가 공통 조상 이후 서로 독립적인 변경 사항을 가지고 있을 때 수행된다.
- 병합 결과로 새로운 병합 커밋이 생성된다.
(2) 동작 조건
- 두 브랜치가 공통 조상 이후 각각 독립적인 변경 사항을 가질 때 발생한다.
- 대상 브랜치
main
에 새로운 커밋이 존재하거나, 병합하려는 브랜치와 충돌이 발생할 가능성이 있는 경우.
(3) 예시
-
Before Merge
main: C0 → C1 → C2 → C3 feature: → C4
-
After Recursive Merge
main: C0 → C1 → C2 → C3 → M (merge commit) ↘ ↗ → C4
C2
는 두 브랜치의 공통 조상 커밋이다.C3(main)
과C4(feature)
의 변경 사항을 병합하여 병합 커밋M
을 생성한다.
(4) 명령어
# main 브랜치로 이동
git checkout main
# feature 브랜치를 병합 (Recursive Merge 자동 수행)
git merge feature
(5) 장단점
- 장점
- 병합 이력이 명확하게 표시되므로, 브랜치 간 병합 내용을 추적하기 용이하다.
- 충돌이 발생할 경우, 충돌 부분을 명시적으로 해결할 수 있다.
- 두 브랜치의 독립적인 변경 사항을 모두 병합하여, 최종 결과를 생성한다.
- 단점
- 병합 커밋이 추가로 생성되기 때문에, 히스토리가 복잡해질 수 있다.
- 충돌이 발생하면 수동으로 해결해야 하므로, 시간이 더 소요될 수 있다.
(6) 충돌 발생 시 처리 방법
-
충돌 확인: 병합 도중 충돌이 발생하면, Git은 이를 감지하고 충돌 파일을 표시한다.
git status
-
충돌 파일 수정: 충돌이 발생한 파일에 다음과 같은 표시가 나타난다. 충돌 부분을 수동으로 수정한다.
<<<<<<< HEAD (main 브랜치의 변경 사항) ======= (feature 브랜치의 변경 사항) >>>>>>> feature
-
병합 완료: 충돌을 해결한 뒤, 수정한 파일을 스테이징하고 병합을 완료한다.
git add <file> git commit
3. Squash Merge
(1) 개념
- Squash Merge는 병합 대상 브랜치의 모든 커밋을 하나로 합쳐 단일 커밋으로 병합하는 방식이다.
- 병합 후, 대상 브랜치에는 병합 브랜치의 세부 커밋 내역이 기록되지 않고 하나의 커밋만 추가된다.
- 주로 작업 내역을 단순화하거나, 작업 단위로 정리하고 싶을 때 사용된다.
(2) 동작 조건
- 대상 브랜치와 병합 브랜치 간에 충돌이 없거나, 충돌을 해결한 뒤 병합할 수 있다.
- 병합 시 기존 브랜치의 커밋 히스토리는 병합 브랜치에 포함되지 않는다.
(3) 예시
-
Before Merge
main: C0 → C1 → C2 feature: → F1 → F2 → F3
-
After Squash Merge
main: C0 → C1 → C2 → S1
S1
은feature
브랜치의 모든 커밋F1
,F2
,F3
을 하나로 압축한 커밋이다.- 병합 브랜치
feature
의 개별 커밋은 대상 브랜치main
에 남지 않는다.
(4) 명령어
# main 브랜치로 이동
git checkout main
# feature 브랜치를 Squash 방식으로 병합
git merge --squash feature
# Squash된 변경 사항을 커밋
git commit -m "Squash feature branch into main"
(5) 장단점
- 장점
- 히스토리를 단순화하여 로그를 깔끔하게 유지할 수 있다.
- 작업 브랜치의 세부 작업 내역을 노출하지 않아도 된다.
- 대상 브랜치에 필요한 결과만 남기므로, 커밋 단위가 많아 복잡한 작업에 적합하다.
- 단점
- 병합 브랜치의 세부 커밋 내역이 사라지므로, 변경 이력을 상세히 추적하기 어렵다.
- 브랜치 간 병합 이력이 명확히 표시되지 않아, 협업 시 작업 내역을 파악하기 어려울 수 있다.
4. Rebase and Merge
(1) 개념
- Rebase and Merge는 병합 브랜치의 커밋을 대상 브랜치의 최신 커밋 위로 재배치하여 병합하는 방식이다.
- 병합 커밋 없이 두 브랜치의 커밋 히스토리를 직선형으로 정리한다.
- 마치 병합 브랜치가 대상 브랜치에서 바로 작업한 것처럼 히스토리를 재정렬한다.
(2) 동작 조건
- 병합하려는 브랜치와 대상 브랜치 모두에 충돌이 없거나, 충돌이 해결된 경우.
- 병합 커밋을 생성하지 않고 히스토리를 간소화하려는 경우.
(3) 예시
-
Before Merge
main: C0 → C1 → C2 feature: → F1 → F2
-
After Rebase and Merge
main: C0 → C1 → C2 → F1 → F2
- 병합 브랜치
featuer
의 커밋F1
,F2
가 대상 브랜치main
의 최신 커밋C2
위에 재배치된다. - 별도의 병합 커밋이 생성되지 않고, 히스토리가 직선형으로 정리된다.
(4) 명령어
# feature 브랜치를 대상으로 Rebase 수행
git checkout feature
git rebase main
# main 브랜치로 이동 후 병합
git checkout main
git merge feature
(5) 장단점
- 장점
- 히스토리가 직선형으로 정리되어 로그가 깔끔해지고, 작업 흐름이 명확히 보인다.
- 병합 커밋 없이 변경 사항을 대상 브랜치에 자연스럽게 적용할 수 있다.
- 대상 브랜치와 병합 브랜치의 커밋이 모두 유지되므로, 작업 내역을 상세히 추적할 수 있다.
- 단점
- Rebase 중 충돌이 발생하면, 모든 충돌을 단계적으로 해결해야 하며, 병합보다 번거로울 수 있다.
- Rebase는 커밋 히스토리를 재작성하므로, 이미 공유된 브랜치에서 Rebase를 사용하면 협업 중 혼란을 초래할 수 있다.
- 어떤 브랜치가 병합되었는지 로그에서 바로 확인하기 어렵다.
5. Merge 방식 비교
특징 | Rebase and Merge | Squash Merge | Recursive Merge (3-Way Merge) | Fast-Forward Merge |
---|---|---|---|---|
병합 커밋 생성 여부 | 병합 커밋 생성되지 않음 | 커밋 압축 후 단일 커밋 생성 | 병합 커밋 생성 | 병합 커밋 생성되지 않음 |
히스토리 구조 | 직선형으로 정리 | 단일 커밋으로 정리 | 병합 이력이 명확히 표시됨 | 직선형 히스토리 유지 |
작업 세부 기록 | 병합 브랜치의 세부 커밋 보존 | 병합 브랜치의 세부 커밋 삭제 | 병합 브랜치와 대상 브랜치 이력 보존 | 병합 브랜치와 대상 브랜치가 동일화 |
적합한 상황 | 직선형 히스토리를 만들고 싶을 때 | 작업 단위를 간소화하고 싶을 때 | 독립적인 변경 사항을 병합할 때 | 대상 브랜치에 변경 사항이 없을 때 |
장점 | 작업 흐름이 깔끔하고 히스토리가 간결 | 히스토리 단순화, 로그가 깔끔 | 변경 내역 추적이 명확 | 추가 커밋 없이 간단한 병합 가능 |
단점 | 충돌 해결이 번거롭고, 공유 브랜치에서 사용 시 위험 | 세부 커밋 내역이 사라져 추적 어려움 | 히스토리가 복잡해질 수 있음 | 병합 이력이 명확하지 않아 추적 어려움 |
댓글남기기