Git 브랜치 운영 전략 소개

Git을 이용한 팀 프로젝트에서 브랜치 전략을 어떻게 구성할까요?

김경태
PentaSecurity Labs
9 min readApr 17, 2023

--

개발에 있어서 소스 형상관리는 필수 이다. 다양한 형상관리 툴들이 존재 해왔지만, 현재 대다수의 개발자들은 Git을 사용 하고 있다. 이 글에서는 Git을 이용하여 형상관리를 할때 브랜치를 운영하는 전략과 배포 관리에 대해 소개 하고자 한다.

Git
개발자라면 이미 숙지 하고 있을 내용이지만 Git의 장점을 간략히 소개 한다.
분산적인 개발 : 전체 개발 내역을 각 개발자의 로컬로 복사하여 개발을 진행 할수 있으며, 개발 내역을 병합(Merge) 할 수 있다. 병합시 문제 발생 소지가 적다.
효율적인 개발 : 다른 형상 관리 시스템보다 성능이 뛰어나며, 변경 내용만 처리 하기 때문에 메모리의 사용 효율성이 뛰어나다.
비선형적 개발 : 브랜치라는 개념을 사용 한다. 이를 이용해 프로젝트에 트리 구조의 가지치기가 가능하고, 이는 비선형 구조로 개발이 가능하도록 해준다.
변경 이력 보장 : 추가 또는 수정된 모든 작업 내역은 Commit으로 관리 한다. Commit은 별도의 영역에서 관리되어 안전하게 프로젝트를 운영 할 수 있도록 한다.

Git 브랜치 전략의 필요성
제품의 기능은 순차적으로 개발되지 않고, 동시 다발적 혹은 우선순의에 의해 개발 순서가 바뀌는 경우가 많다. 용도에 맞는 브랜치 운영이 없다면 이전에 중단되었던 기능 개발 이력 추적 등 개발 운용이 복잡해진다. 차기 버전 개발 도중 이전 버전에 이슈 또는 장애가 발생하여 긴급한 패치가 필요한 상황이 발생하면 개발 충돌이 발생할 가능성이 높아 지고 운용이 힘들어진다. 각 용도에 맞는 브랜치의 사용은 개발의 일시 중단, 순서 변경에 유연하게 대처 가능하게 한다. 또한 이미 배포한 버전에서 발생한 이슈, 장애에 대한 핫픽스 배포를 용이 하게 해준다.

Git 브랜치 전략 소개
2010년 Vincent Drienssen 에 의해 소개된 전략 모델인 ‘Git Flow’ 전략을 기반으로 팀의 상황에 맞도록 적용한 전략을 소개 하고자 한다.(잘 알려진 Git 브랜치 운영 전략으로 ‘Git Flow’, ‘Github Flow’, ‘Gitlab Flow’ 들이 있다.)
Git Flow 전략은 이미 많은 곳에서 기본 모델로 채용 하고 있는 검증된 모델이다. 용도에 따라 크게 메인 브랜치와 보조 브랜치로 구성된다. 메인 브랜치는 추가된 기능이 취합되고, 최종 배포를 위한 브랜치로 중앙 저장소에 영원히 유지 된다. 보조 브랜치는 기능 구현, 배포를 준비, 배포한 버전의 버그를 수정하는 브랜치이다.

Overall

Git 브랜치 전략 전체 플로우
Git 브랜치 전략 전체 플로우

메인 브랜치
기존 Git의 핵심 개념인 master, develop 브랜치로 구성 된다. 중앙 저장소에 영구히 유지 되어야 한다.
master : 기능 개발, 버그 수정이 완료되어 이미 배포 되었거나 곧 배포할 소스가 관리 되는 브랜치
develop : 추가 되어야 할 기능 소스들이 관리 되는 브랜치
모든 기능이 추가되고, 안정되어 배포할 준비가 완료 되면 develop브랜치를 master브랜치에 병합 하고 배포 버전 태그를 단다.(* 간략한 표현으로, 실제 전략은 이후 소개할 보조 브랜치인 release브랜치로 임시 파생하고 검증이 완료 된 후 master브랜치에 병합 하고 배포 버전 태그를 단다.)

메인 브랜치 플로우
메인 브랜치 플로우

보조 브랜치
메인 브랜치 외에 보조 브랜치가 필요 하다. 우리는 기능 구현, 배포 준비, 배포된 버전에 대한 버그를 해결을 동시에 진행 해야 한다. 이러한 이유로 다양한 보조 브랜치가 필요 하다.
사용할 보조 브랜치의 종류는 다음과 같다.
feature 브랜치
release 브랜치
hotfix 브랜치
site 버전 브랜치
각 브랜치 마다 목적을 가지고 있으며, 어떤 브랜치로 부터 파생될지, 어떤 브랜치로 병합되어야 할지에 대한 규칙이 존재 한다.

feature 브랜치
기능 개발을 위한 브랜치 이다. 특정 기능 개발을 위해 develop 브랜치로 부터 파생되며, 해당 기능 개발을 완료 할 때 까지 유지 한다. 개발이 완료된후 develop 브랜치에 병합 한다. 병합 이후 브랜치를 파기하는것이 기본이나, 상황에 따라 유지 해도 무방하다. feature브랜치는 origin에 push하지 않는것을 기본으로 하나 상황에 따라 유연하게 운영 한다.
파생된 소스 브랜치 : develop
병합할 브랜치 : devlop
브랜치 이름 규칙 : master, develop, release-*, hotfix-* 를 제외한 기능을 간략히 표현 할 수 있는 이름

Feature 브랜치 플로우
Feature 브랜치 플로우

feature 브랜치의 병합
Git의 기본 병합 방식은 fast-forward이다. fast-forward로 병합 시 feature브랜치에서 실행한 모든 커밋이 develop브랜치에 병합 된다. 이는 기능 구현한 커밋의 경계를 찾기 어렵게 한다. 커밋 메시지를 하나하나 찾아야 한다. 추가한 기능을 되돌려야(revert) 할 때 기능과 관련된 모든 커밋을 되돌려야 하는데 병합 커밋이 없다면 힘든 작업이 될것 이다.
‘ — no-ff’ 옵션을 이용한 병합 또는 rebase는 이러한 문제들을 해결 할 수 있다.
‘ — no-ff’옵션은 fast-forward를 사용하지 않고 병합 커밋을 생성, 병합 시점과 병합된 커밋들을 쉽게 되돌릴 수 있다.
rebase는 파생되는 커밋을 줄여 ‘git log’명령을 통한 이력 추적을 수월하게 한다. rebase는 항상 fast-forward로 머지 하도록 한다.
* 위 병합 방식의 적용 여부는 팀의 상황에 따라 결정 하도록한다. 병합시 복잡도가 올라가고 그에 따라 실수가 발생할 소지도 있기 때문이다. 원작자(Vincent Drienssen)는 ‘ — no-ff’옵션 사용을 권장 하고 있다.

Feature 브랜치 병합 시 ‘ — no-ff’옵션 적용 유무의 차이
Feature 브랜치 병합 시 ‘ — no-ff’옵션 적용 유무의 차이

release 브랜치
배포를 준비 하는 임시 브랜치 이다. 버전 등 메타 데이터를 수정하고 검증 후 발생한 버그들을 수정 한다. BAT 및 QA를 진행 하는 브랜치이다. develop브랜치에 추가되어야 할 모든 기능들이 병합되고 소스가 안정되었다면 release브랜치를 생성한다. QA진행 중 n차 회귀테스트를 위한 패키지들 배포시 master 와 develop에 병합 하고 태그를 단다. 마지막으로 QA가 완료 된후 Stable이 선언되면 Stable에 맞는 버전으로 변경 하여 master, develop에 병합 하도록 한다. release브랜치를 활용 함으로써 배포기간 에도 추가 기능을 develop브랜치에서 진행 할 수 있다. 모든 진행이 완료 된 후 release브랜치는 삭제 하는 것을 기본으로 한다. 하지만 이 브랜치 역시 팀의 상황에 따라 유연하게 운영 가능하다.
파생된 소스 브랜치 : develop
병합할 브랜치: develop 과 master
브랜치 이름 규칙 : release-<버전>

Release 브랜치 플로우
Release 브랜치 플로우

hotfix 브랜치
이미 배포한 버전에 심각한 버그가 발생하여 수정이 필요 할 경우 운영 하는 브랜치 이다. master브랜치의 해당 버전 태그로부터 생성 한다. 수정 완료 후 release브랜치와 동일한 방식으로 develop 과 master브랜치에 병합 하고 태그를 달고 hotfix브랜치를 삭제 하는 것을 기본으로 한다. 하지만 문제가 발생한 버전 이후 상당히 많은 버전이 배포 되었다면, develop과 master브랜치에 병합 시 영향도가 상당히 클수 있다. 이 경우 수정 내용을 별도로 develop에 반영하고 hotfix 브랜치를 유지하는 방안도 고려 해야 한다. 소스의 영향도를 판단하여 상황에 따라 대처 해야 한다.
파생된 소스 브랜치 : master(tag)
병합할 브랜치 : develop과 master(소스 영향도에 따라 병합하지 않고 변경 내용을 별도로 적용한다.)
브랜치 이름 규칙 : hotfix-<버전>

Hotfix 브랜치 플로우
Hotfix 브랜치 플로우

site 버전 브랜치
특정 사이트에만 배포될 버전을 관리 하는 브랜치이다. 운영하지 말아야 하는 브랜치이다. 가급적 요구 기능을 일반화하여 전체에 적용 할 수 있도록 하길 권장 한다. 다시한번 강력하게 운영하지 않기를 권하는 브랜치이다. 그럼에도 불구하고 어쩔수 없는 경우 생성 한다. master브랜치의 특정 버전 태그로 부터 생성 한다. 기능 개발이 완료된 이후 특정 사이트에 한정된 기능이기 때문에 그어떤 브랜치에도 병합하지 않는다. site 버전 브랜치는 해당 사이트 유지보수를 위해 유지 해야 한다. 만약 특정 사이트를 위한 기능이 일반 버전에도 추가 될 필요가 있을경우 develop에 병합 한다. 병합시 많은 충돌과 문제를 야기 할수 있으므로 각별한 주의가 필요 하다. 소스를 별도로 적용 하는 방안도 고려 할 수 있다.
파생된 소스 브랜치 : master(tag)
병합할 브랜치 : 없음
브랜치 이름 규칙 : <사이트>-<버전>-<사이트 버전>

Site 버전 브랜치 플로우
Site 버전 브랜치 플로우

이상 현재 팀에서 운영하고 있는 Git브랜치 전략 방안을 소개 했다. 각 팀이 맡고 있는 프로젝트의 특성에 따라, 구성원 또는 팀 개발 문화에 따라 위 전략을 간략화 또는 더 고도화 하여 사용 할 수 있다. 다만 Git을 사용 하면서 master, develop 브랜치에서 모든 개발과 배포를 진행 하면서 Git을 활용 하지 못하는 경우가 없기를 바라며 전략을 소개를 마칩니다.

참고링크
‘A successful Git branching model’ by Vincent Driessen : https://nvie.com/posts/a-successful-git-branching-model/

--

--