Git의 다양한 병합 방법으로 일반적인 Merge, Fast-Forward Merge, Squash Merge, Rebase에 대해서 설명하겠습니다.

1. 일반적인 Merge

일반적인 Merge는 두 개의 분기된 브랜치를 병합할 때 사용되며, 병합 커밋이 생성되어 두 브랜치의 히스토리를 모두 보존합니다.

  • 예시 명령어
bash
# main 브랜치로 이동
git checkout main

# feature 브랜치를 main에 병합 (병합 커밋 생성됨)
git merge feature

일반적인 Merge 주의사항

✅ 주의할 점

  • 불필요한 병합 커밋 증가
    • 병합할 때 마다 새로운 merge commit이 생성되므로, 잦은 병합 시 불필요한 커밋이 많아져 히스토리가 복잡해질 수 있음.
  • 충돌 발생 가능
    • 두 브랜치에서 같은 파일을 수정했다면 충돌(merge conflict)이 발생할 수 있으며, 이를 수동으로 해결해야 함.

⚠️ 문제 상황: 병합 커밋이 너무 많아지는 경우

bash
git checkout main
git merge feature
  • 만약 feature 브랜치에서 많은 작은 커밋들이 있었다면, 병합 시 모든 커밋 내역이 유지되고 추가로 병합 커밋이 생성됨.
  • 잦은 병합을 하면 git log가 merge commit으로 가득 차서 지저분해질 수 있음.

🔧 해결 방법

  1. 만약 작은 커밋들을 합치고 싶다면 squash merge를 고려할 것.
  2. 만약 히스토리를 단순하게 유지하고 싶다면 rebase를 고려할 것.

2. Fast-Forward Merge

Fast-Forward Merge는 병합 대상 브랜치에 새로운 커밋이 없을 때, 단순히 브랜치 포인터를 이동시켜 병합 커밋 없이 히스토리를 유지하는 방법입니다.

  • 예시 명령어
bash
# main 브랜치로 이동
git checkout main

# Fast-Forward Merge 수행 (병합 커밋 없이 브랜치 포인터 이동)
git merge --ff feature

Fast-Forward Merge 주의사항

✅ 주의할 점

  • 히스토리가 단순해지지만, 독립적인 개발 흐름을 유지하기 어려움
    • Fast-Forward Merge는 기존 커밋 뒤에 그대로 붙이므로, 브랜치의 독립적인 개발 흐름을 나타낼 수 없음.
  • 병합 커밋이 없으므로, 브랜치 병합 기록을 확인하기 어려움
    • git log --graph로 보면 분기가 없이 연속된 커밋처럼 보임.

⚠️ 문제 상황: 브랜치 병합 기록이 남지 않음

bash
git checkout main
git merge --ff feature
  • feature 브랜치에서 작업한 내용이 그냥 main 브랜치에 추가됨.
  • git log에서 feature 브랜치가 어디에서 시작되었는지 기록이 남지 않음.
  • 협업 시, 특정 기능이 언제 개발되었는지 추적이 어려워질 수 있음.

🔧 해결 방법

병합 커밋을 남기고 싶다면 --no-ff 옵션을 사용.

bash
git merge --no-ff feature
git log --graph를 통해 히스토리를 가시적으로 유지할 수 있음.

3. Squash Merge

Squash Merge는 여러 개의 커밋을 하나로 합쳐서 병합하는 방법으로, 깔끔한 히스토리를 유지하는 데 유용합니다.

  • 예시 명령어
bash
# main 브랜치로 이동
git checkout main

# Squash Merge 수행 (병합 후 커밋들을 하나로 합침)
git merge --squash feature

# Squash된 상태에서 수동으로 하나의 커밋을 생성
git commit -m "단일 커밋으로 병합된 기능 분기 변경 사항"

Squash Merge 주의사항

✅ 주의할 점

  • 모든 커밋이 하나로 합쳐지므로, 개별 커밋 내역이 사라짐
    • 작은 커밋들을 합쳐서 히스토리를 깔끔하게 만들 수 있지만, 개별 커밋 내역이 사라지므로 과거 특정 변경 사항을 찾기 어려움.
  • 협업 시 원본 커밋을 유지해야 하는 경우 주의해야 함
    • 팀원들의 커밋이 합쳐질 때, 누가 어떤 기여를 했는지 알기 어려움.

⚠️ 문제 상황: 개별 커밋 내역이 사라짐

bash
git checkout main
git merge --squash feature
git commit -m "단일 커밋으로 병합된 기능 분기 변경 사항"
  • feature 브랜치에 여러 개의 작은 커밋이 있었더라도, 병합 시 하나의 커밋으로 기록됨.
  • git log에서 feature 브랜치의 커밋이 사라지고 하나의 커밋만 남음.

🔧 해결 방법

  • 개별 커밋을 유지하고 싶다면 일반 merge 사용.
  • 협업이 필요할 경우, squash merge 전에 팀원들과 논의 필요.
  • 자신만의 브랜치에서 squash merge 후, 정리된 커밋을 push.

4. Rebase

Rebase는 한 브랜치의 변경 사항을 다른 브랜치의 최신 커밋 위로 재배치하여 히스토리를 재구성하는 방법입니다.

  • 예시 명령어
bash
# feature 브랜치로 이동
git checkout feature

# feature 브랜치를 main 브랜치의 최신 커밋 위로 재배치
git rebase main

# 만약 충돌이 발생하면 해결한 후
git add .

# Rebase 계속 진행
git rebase --continue

Rebase 주의사항

✅ 주의할 점

  • 공유된 브랜치에서 rebase 하면 안 됨
    • git rebase는 새로운 커밋 해시를 생성하므로, 이미 원격 저장소에 push된 브랜치에 rebase를 하면 동료들이 충돌을 겪을 수 있음.
  • 충돌 발생 가능성이 높음
    • Rebase 도중 충돌이 발생하면, 이를 순차적으로 해결하고 계속 진행해야 함.

⚠️ 문제 상황: 원격 브랜치에서 Rebase를 수행한 경우

bash
git checkout feature
git rebase main
  • feature 브랜치를 main 브랜치의 최신 커밋 위로 이동.
  • 하지만 feature 브랜치가 이미 원격 저장소에 push된 경우, 팀원들의 로컬 브랜치와 커밋 해시가 달라져 충돌 발생.

🔧 해결 방법

  • 이미 공유된 브랜치에서는 git merge를 사용하고, rebase는 개인 브랜치에서만 사용.
  • 만약 원격 브랜치에서 rebase를 수행했다면, 강제 push가 필요하지만 팀원들에게 영향을 주므로 신중히 결정해야 함.
bash
git push --force

하지만 가능하면 git rebase는 로컬에서만 수행하고, 공유된 브랜치에서는 merge를 사용하는 것이 안전.

[출처]Fast-Forward MergeRebase