Fast-forward merge와 3-way merge의 차이를 이해하고, 충돌이 발생하는 원인과 해결 방법을 배운다. rebase와 merge의 차이, squash merge 등 실무에서 쓰이는 병합 전략을 익힌다.
병합(Merge) — 브랜치를 하나로 합치기
브랜치에서 작업이 완료되면 다른 브랜치(주로 main이나 develop)에 병합해야 합니다. Git의 병합은 두 가지 방식으로 이루어집니다.
Fast-Forward Merge
분기 이후 main에 새 커밋이 없을 때 발생합니다. 별도의 병합 커밋 없이 단순히 main 포인터가 앞으로 이동합니다.
병합 전:
A - B - C (main)
\
D - E (feature)
병합 후 (fast-forward):
A - B - C - D - E (main, feature)
명령:
git switch main
git merge feature/login # Fast-forward 자동 발생
# Fast-forward 방지 (항상 병합 커밋 생성)
git merge --no-ff feature/login
3-Way Merge
분기 이후 main에도 새 커밋이 생겼을 때 발생합니다. 공통 조상과 두 브랜치의 끝을 3개 지점으로 비교해 새 병합 커밋을 만듭니다.
병합 전:
A - B - C - F (main)
\
D - E (feature)
병합 후 (3-way merge):
A - B - C - F - M (main) <-- M이 병합 커밋
\ /
D - E
명령:
git switch main
git merge feature/login # 3-way merge 커밋 자동 생성
충돌(Conflict) — 발생 원인과 해결
두 브랜치가 같은 파일의 같은 줄을 서로 다르게 수정했을 때 충돌이 발생합니다. Git은 자동으로 해결할 수 없어 개발자에게 판단을 요청합니다.
git merge feature/login
# CONFLICT (content): Merge conflict in src/auth.js
# Automatic merge failed; fix conflicts and then commit the result.
git status # 충돌 파일 확인
# both modified: src/auth.js
충돌 마커 해석
충돌이 난 파일 내용:
<<<<<<< HEAD
const timeout = 3000; // main 브랜치의 내용
=======
const timeout = 5000; // feature 브랜치의 내용
>>>>>>> feature/login
해결 순서:
1. 편집기에서 <<<<<<<, =======, >>>>>>> 마커 찾기
2. 어떤 내용을 남길지 결정 (또는 두 내용 통합)
3. 마커 제거, 최종 내용만 남기기
4. git add 해당파일
5. git commit (메시지 자동 생성됨)
충돌 해결 도구
# VS Code에서 충돌 파일 열기 → 버튼으로 선택
# "Accept Current Change" → HEAD(현재 브랜치)
# "Accept Incoming Change" → 병합하는 브랜치
# "Accept Both Changes" → 둘 다 유지
# 머지 도구 실행
git mergetool
# 병합 중단 (원래 상태로 복귀)
git merge --abort
Rebase — 이력을 깔끔하게
rebase는 브랜치의 기준점을 다른 커밋으로 옮기는 작업입니다. merge와 달리 선형 이력을 만듭니다.
merge 결과 (병합 커밋 존재):
A - B - C - F - M (main)
\ /
D - E
rebase 결과 (선형 이력):
A - B - C - F - D2 - E2 (main)
-- D, E가 F 뒤로 재배치됨 (커밋 해시 변경!)
명령:
git switch feature/login
git rebase main # feature를 main 위에 재배치
git switch main
git merge feature/login # 이제 fast-forward merge
| 항목 | merge | rebase |
|---|---|---|
| 이력 형태 | 비선형 (병합 커밋) | 선형 (깔끔) |
| 커밋 해시 | 유지됨 | 변경됨 |
| 원본 보존 | 정확한 히스토리 | 정리된 히스토리 |
| 사용 상황 | 팀 작업, 중요 병합 | 개인 브랜치 정리 |
| 황금 규칙 | 제한 없음 | 공유된 브랜치에 사용 금지! |
rebase의 황금 규칙: 이미 원격에 push된 공유 브랜치를 rebase하면 팀원들의 이력이 꼬입니다. 개인 기능 브랜치를 main에 올리기 전에 정리할 때만 사용하세요.
Squash Merge — 여러 커밋을 하나로
# feature 브랜치의 여러 커밋을 하나로 압축해서 main에 추가
git switch main
git merge --squash feature/login
git commit -m "feat: 로그인 기능 추가"
# 결과: feature의 5개 커밋이 main에서 1개 커밋으로 정리됨
# 단점: feature 브랜치 삭제 후 어떤 작업인지 추적 어려움
태그 — 중요한 커밋 표시
# 경량 태그 (단순 포인터)
git tag v1.0.0
# 주석 태그 (권장 — 메시지, 작성자 포함)
git tag -a v1.0.0 -m "Release version 1.0.0"
# 특정 커밋에 태그
git tag -a v0.9.0 abc1234
# 태그 목록
git tag
git tag -l "v1.*" # 패턴 검색
# 태그 원격 전송 (push로 자동 전송 안 됨!)
git push origin v1.0.0
git push origin --tags # 전체 태그
관련 검색어 · git merge 충돌 해결, fast-forward 3-way merge, git rebase 차이, squash merge, git tag, 충돌 마커 해석