브랜치와 머지 전략
Git 기반의 버전 관리에서 브랜치 전략은 효율성을 극대화하고, 코드 품질을 유지하는 데 중요한 역할을한다. 이번 장에서는 대표적인 Git 브랜치 전략들을 살펴보고, 각 전략의 특징과 장단점을 알아본다.
브랜치 전략
Git 브랜치 전략(Branching Strategy)은 여러 개발자가 하나의 프로젝트에서 동시에 작업할 때 코드의 충돌을 방지하고 배포의 안정성을 확보하기 위해 정의한 협업 규칙이다. 효율적인 전략은 코드 관리의 복잡도를 낮추고 지속적 통합 및 배포(CI/CD)를 원활하게 한다.
처음 Git으로 프로젝트를 시작할때 가장 고민되는 부분이 어떻게 브랜치를 나눠 작업하고 통합해 나갈지에 대한 부분이다.기본적으로 프로젝트의 규모, 팀의 크기, 배포 주기 등에 따라 적합한 브랜치 전략이 달라질 수 있으나 대표적으로 많이 사용되는 브랜치 전략으로 Git Flow, GitHub Flow가 있다.
| 전략 | 장점 | 단점 | 적합한 프로젝트 |
|---|---|---|---|
| Git Flow | 배포 주기가 길고 관리가 엄격한 환경에 유리 | 브랜치 구조가 복잡하고 관리 오버헤드 발생 | 모바일 앱, 패키지 SW |
| GitHub Flow | 구조가 단순하며 빠른 배포와 피드백 가능 | 테스트 자동화(CI)가 미흡할 경우 안정성 저하 | 웹 서비스 SaaS |
Sponsored
Git Flow
Git Flow는 Vincent Driessen이 제안한 브랜치 전략으로, 복잡한 프로젝트에 적합하다. 주요 브랜치는 다음과 같다.
graph LR
Main[Main Branch] --- Hotfix(Hotfix)
Main --- Release(Release)
Release --- Develop[Develop Branch]
Develop --- Feature1(Feature A)
Develop --- Feature2(Feature B)
- main: 항상 배포 가능한 상태를 유지하는 브랜치.
- develop: 다음 릴리스를 위한 통합 브랜치로, 모든 기능 개발이 완료된 후 이 브랜치에 병합된다.
- feature: 새로운 기능 개발을 위한 브랜치로, develop 브랜치에서 분기된다.
- release: 릴리스 준비를 위한 브랜치로, develop 브랜치에서 분기되어 버그 수정 및 최종 테스트가 이루어진다.
- hotfix: 배포된 버전에서 긴급한 버그 수정을 위한 브랜치로, master 브랜치에서 분기된다.
각 브랜치의 협업 과정을 좀 더 자세히 표현하면 다음과 같다.
---
config:
theme: 'forest'
---
gitGraph
commit id: "Tag 0.1"
branch develop
checkout develop
commit id: "Initial Develop"
branch feature
checkout feature
commit id: "Feature for future release"
commit id: "Major feature"
checkout develop
merge feature
branch release
checkout release
commit id: "Start of release branch for 1.0"
commit id: "Only bugfixes!"
checkout develop
merge release
checkout main
merge release tag: "1.0"
checkout main
branch hotfix
checkout hotfix
commit id: "Severe bug fixed: hotfix 0.2"
checkout main
merge hotfix tag: "0.2"
checkout develop
merge hotfix
Sponsored
GitHub Flow
GitHub Flow는 단순하고 직관적인 브랜치 전략으로 Git Flow의 복잡성을 제거한 전략으로, 수시로 배포가 일어나는 클라우드 서비스 및 웹 애플리케이션 개발에 적합하다. 주요 브랜치는 다음과 같다.
graph LR
Main[Main Branch] --- Feature1(Feature A)
Main --- Feature2(Feature B)
- main: 항상 배포 가능한 상태를 유지하는 브랜치.
- feature: 새로운 기능 개발을 위한 브랜치로, main 브랜치에서 분기된다. 기능 개발이 완료되면 Pull Request를 통해 main 브랜치에 병합된다.
좀 더 자세한 협업 과정을 표현하면 다음과 같다.
---
config:
theme: 'forest'
---
gitGraph
commit id: "Initial Commit"
branch "feature/login"
checkout "feature/login"
commit id: "feat: add login form"
commit id: "feat: connect auth API"
checkout main
merge "feature/login" tag: "v1.1.0"
branch "fix/typo"
checkout "fix/typo"
commit id: "fix: update readme"
checkout main
merge "fix/typo"
commit id: "Deploy to Prod"
병합 전략
Git에서 브랜치를 병합하는 방법에는 여러 가지 전략이 있다. 각 전략은 프로젝트의 요구사항과 협업 방식에 따라 적합한 상황이 다르다. 대표적인 병합 전략으로는 05. 풀 리퀘스트에서도 잠시 언급한것 처럼 Create a merge commit, Squash and merge, Rebase and merge가 있다.
각각의 방법에 대한 특성과 장단점을 정확하게 이해하고 상황에 맞게 선택하는 것이 중요하다. 여기서는 각 병합 전략에 대해 자세히 살펴보고 구체적인 동작 형태는 07. 실전 튜토리얼에서 실습을 통해 알아보도록 한다.
Create a merge commit
Create a merge commit은 소스 브랜치의 모든 커밋이 타겟 브랜치에 병합되는것으로 Github에서 기본으로 제공하는 병합 옵션이다. 예를 들어 소스 브랜치에 3개의 커밋(C1, C2, C3)이 있다면 히스토리를 유지하면서 이를 병합하는 커밋이 대상 브랜치에 추가 및 연결된다. 이 방법은 병합 이력이 명확하게 남기 때문에, 추후 확인할 때 유용하다.
---
config:
theme: 'forest'
---
gitGraph
commit id: "Initial"
branch feature
checkout feature
commit id: "C1"
commit id: "C2"
commit id: "C3"
checkout main
merge feature id: "Merge commit"
Squash and merge
Squash and merge는 소스 브랜치의 모든 커밋을 하나로 압축(Squash)해서 타겟 브랜치에 한 번에 추가하는 옵션이다. 예를 들어, 소스 브랜치에 3개의 커밋이 있어도, 대상 브랜치에는 하나의 병합 커밋만 추가되는 형식이다. 이 방법은 중요하지 않은 작은 커밋들을 깔끔하게 정리할 수 있지만, 추후 이력을 정확하게 확인하기 어려워 주의가 필요하다.
---
config:
theme: 'forest'
---
gitGraph
commit id: "Initial"
branch feature
checkout feature
commit id: "C1 (ignored)"
commit id: "C2 (ignored)"
commit id: "C3 (ignored)"
checkout main
commit id: "Squash merge commit"
Rebase and merge
Rebase and merge는 소스 브랜치의 모든 커밋을 그대로 타겟 브랜치에 추가하는 옵션이다. 예를 들어, 소스 브랜치에 3개의 커밋이 있으면, 대상 브랜치에 직렬로 3개의 커밋(a, b, c)이 추가된다. fast-forward 형태의 병합을 원하는 경우 rebase를 통해 커밋들을 재배치한 후 병합할 수 있다. 이 방법은 병합 커밋을 생성하지 않고 커밋을 쌓아갈 수 있어서 직관적이지만, 여러 브랜치를 병합할 때 복잡한 충돌이 발생할 수 있어 주의가 필요하다.
---
config:
theme: 'forest'
---
gitGraph
commit id: "Initial"
branch feature
checkout feature
commit id: "C1"
commit id: "C2"
commit id: "C3"
checkout main
cherry-pick id: "C1"
cherry-pick id: "C2"
cherry-pick id: "C3"
main에 feature의 커밋들이 직렬로 추가된 모습을 보인다. 추가로 merge 과정을 통해 fast-forward 형태로 병합을 완료하면서 병합 커밋을 남길 수도 있다.
각 전략의 특징을 정리하면 다음과 같다.
| 전략 | 히스토리 형태 | 장점 | 권장 상황 |
|---|---|---|---|
| Create merge commit | 비선형 (가지가 갈라짐) | 모든 맥락 유지 | 협업 규모가 크고 상세 기록이 필요할 때 |
| Squash and merge | 선형 (1개의 커밋) | 매우 깔끔한 히스토리 | 작은 기능 구현 후 지저분한 커밋 정리 |
| Rebase and merge | 선형 (모든 커밋 나열) | 가독성이 좋고 흐름 파악 용이 | 개인 작업 브랜치를 깔끔하게 유지하고 싶을 때 |