LabHub

Git 실전 · 브랜치 전략 · 이론

전략을 고르는 질문은 하나다

LabHub 에서 이어서 보기

한 줄 요약

브랜치 전략을 고르는 질문은 "어떤 그림이 예쁜가"가 아니라 "장애가 났을 때 이 저장소에서 원인 커밋을 어떻게 찾을 계획인가"다.

왜 이게 필요했나

Git Flow, GitHub Flow, Trunk-Based 는 서로 다른 배포 주기를 전제로 만들어졌다. 전제를 무시하고 이름만 가져오면 매일 마찰이 생긴다.

| 전략 | 브랜치 종류 | 병합 빈도 | 맞는 곳 |
| --- | --- | --- | --- |
| Git Flow | 5종 이상 | 주 1~2회 | 정기 릴리스, 모바일 앱, 패키지 |
| GitHub Flow | 2종 | 일 1~3회 | CD 를 실천하는 SaaS |
| Trunk-Based | 1~2종 | 일 5~10회 이상 | 브랜치 수명 1일 이내, Feature Flag 필수 |

Trunk-Based 는 CI 요구 수준이 매우 높다. Feature Flag 없이 시작하면 미완성 코드가 그대로 배포된다. 반대로 GitOps 환경에서 Git Flow 의 release 브랜치는 자동 동기화 패턴과 마찰이 크다. 그래서 GitOps 를 쓴다면 GitHub Flow 또는 Trunk-Based 를 권한다.

공통 규칙 하나는 어디서나 통한다. 3일 이상 살아 있는 feature 브랜치는 merge conflict 의 온상이다.

어떻게 동작하나

병합 방식은 세 가지고 각각 다른 것을 남긴다.

체리픽은 저장된 diff 를 오려 붙이는 것이 아니다. Git 은 애초에 diff 를 저장하지 않고 스냅숏만 저장한다. 그래서 대상 커밋의 부모 트리를 공통 조상으로 삼아 삼자 병합을 수행한다. 체리픽이 충돌하는 이유가 여기에 있다.

현장에서 만나는 모습

핫픽스를 릴리스 브랜치에서 고치고 main 에 반영하지 않아 다음 릴리스에서 같은 버그가 되살아나는 일은 어느 팀에나 한 번은 생긴다. 릴리스 브랜치를 운영한다면 "핫픽스는 반드시 main 으로도 가져온다"가 정책 문장으로 적혀 있어야 한다.

태그도 마찬가지다. 가벼운 태그는 그냥 포인터라 누가 언제 왜 붙였는지 남지 않는다. 릴리스 태그는 -a 로 주석을 붙여야 나중에 조사에 쓸 수 있다.

다음 실습에서 할 것

저장소를 처음부터 만들고, 기능 브랜치를 --no-ff 로 병합해 통합 기록을 남기고, 작은 수정은 빨리 감기로 올리고, 릴리스 태그를 붙이고, 릴리스 브랜치의 핫픽스를 체리픽으로 main 에 반영한 뒤, 병합된 브랜치만 골라 정리합니다. 마지막에는 이 저장소의 실제 숫자를 세어 전략 비교표를 씁니다.