Git branch 전략

브랜치의 중요성

브랜치는 코드베이스를 독립적으로 관리할 수 있게 해주는 Git의 중요한 기능입니다. 브랜치를 사용하면 독립적인 환경에서 기능을 개발하거나 버그를 수정할 수 있으며, 여러 사람이 병렬적으로 작업할 수 있습니다. 메인 브랜치에서만 작업할 경우 여러 문제가 발생할 수 있습니다:

  1. 불완전한 코드: 기능 개발 중 여러 개의 커밋이 발생하면, 메인 브랜치가 불완전한 코드로 가득 차게 됩니다.
  2. 협업 문제: 여러 개발자가 같은 브랜치에서 작업하면 파일 충돌이 발생하고, 커밋 히스토리가 뒤죽박죽 섞입니다.
  3. 롤백 어려움: 커밋 히스토리가 복잡하게 얽혀 있어 특정 시점으로 롤백하기 어려워집니다. 브랜치를 사용하면 이러한 문제를 해결할 수 있습니다. 새로운 기능을 개발하거나 버그를 수정할 때, 독립적인 브랜치에서 작업한 후, 완료되면 메인 브랜치에 안전하게 병합할 수 있습니다. 또한, 실험적인 작업도 별도의 브랜치에서 수행하여 쉽게 삭제할 수 있습니다.

Git 브랜치 전략

브랜치를 효과적으로 관리하기 위해 여러 브랜치 전략이 존재합니다. 대표적으로 Git Flow와 Github Flow가 있습니다.

Git Flow

Vincent Driessen이 2010년에 제안한 Git Flow는 다음과 같이 브랜치를 관리합니다:

  • Main 브랜치: 출시 가능한 프로덕션 코드를 모아두는 브랜치입니다.
  • Develop 브랜치: 다음 버전 개발을 위한 브랜치로, 기능 개발이 완료되면 Main 브랜치로 병합됩니다.
  • Feature 브랜치: 하나의 기능을 개발하기 위한 브랜치로, Develop 브랜치에서 생성하여 기능 개발이 완료되면 다시 Develop 브랜치로 병합됩니다.
  • Release 브랜치: 배포 준비를 위한 브랜치로, Develop 브랜치에서 생성하여 버그 수정 등을 한 후 Main과 Develop 브랜치로 병합됩니다.
  • Hotfix 브랜치: 배포된 버전에서 발생한 문제를 수정하기 위한 브랜치로, Main 브랜치에서 생성하여 문제 해결 후 Main과 Develop 브랜치로 병합됩니다.

특징

브랜치 관리 규약이 복잡하다

A successful Git branching model 에서는 feature, release, hotfix 세 가지의 보조 브랜치가 어디서 생성될 수 있으며, 어디로 머지(Merge)되어야 하는지, 그리고 어떤 이름을 가질 수 있는지 상세하게 설명합니다. 이러한 규약을 익히는 것도 어려운 점 중 하나이지만, 규약으로 인해 브랜치 관리의 본질적인 복잡성이 증가하는 것 또한 문제가 됩니다. 이러한 복잡성을 보여주는 예시를 간단히 짚어보자면 아래와 같습니다.

release 와 hotfix 브랜치를 머지하기 복잡합니다. 기본적으로 두 종류의 브랜치는 변경 사항이 덮어씌워지는 것을 방지하기 위해 master와 develop에 동시에 머지되어야 하며, 활성화된 release 브랜치가 있다면 이것도 신경써야 합니다. 새로운 작업을 feature 브랜치와 hotfix 브랜치 중 어떤 것으로 해야 할지 판단하기 어렵습니다. 일반적으로는 계획된 기능을 feature, 계획되지 않은 픽스를 hotfix로 하지만 이런 분류가 애매해지는 순간이 분명 존재합니다. hotfix에서 새로 발생한 변경 사항을 feature 브랜치에 적용하고 싶다면, 최소 3번의 머지가 필요합니다. (hotfix -> master, hotfix -> develop, develop -> feature)

브랜치가 오래 유지된다

Git Flow에서는 브랜치가 보통 오래 유지되고, 상대적으로 많은 변경사항을 한 번에 머지하는 것을 선호합니다. 이러한 선호는 여러가지 부작용을 같이 야기합니다.

먼저, 서로 다른 두 브랜치에서 독립적으로 작업을 하게 되면 동시에 수정한 부분이 생길 수 있는데, 이 때 두 브랜치를 머지하기 위해서는 Git 상에서 컨플릭트를 해결해야 합니다. 두 브랜치가 각각 독립적으로 오래 작업되었을수록, 컨플릭트는 보통 더 크고 해결하기 어려워집니다. 컨플릭트 해결 중 발생하는 휴먼 에러로 버그를 만들 확률 또한, 컨플릭트의 규모가 커질수록 같이 증가합니다.

Git Flow는 명시적으로 버전을 관리해야 하는 프로젝트에 적합합니다. 예를 들어, 스마트폰 앱이나 오픈소스 라이브러리/프레임워크 등입니다. 하지만 웹 애플리케이션과 같이 지속적 배포가 필요한 경우에는 적합하지 않을 수 있습니다.

Github Flow

Github Flow는 간단하고 효율적인 브랜치 전략으로, 다음과 같이 관리합니다:

  • Main 브랜치: 항상 안정적인 상태여야 하며, 모든 커밋은 배포 가능해야 합니다.
  • Topic 브랜치: 새로운 기능 개발이나 버그 수정을 위한 브랜치로, Main 브랜치에서 생성하여 작업을 완료한 후 Main 브랜치에 병합합니다. Github Flow는 자동화를 적극 활용하며, PR(Pull Request)을 통해 코드 리뷰와 토론을 진행합니다. 개발팀이 소규모 애자일 팀이고, 제품이 단일 릴리즈 버전만 존재하는 경우 적합합니다. 대부분의 웹 애플리케이션이 이에 해당합니다.

특징

  1. master 브런치는 어떤 때든 배포가 가능하다. master 브런치는 항상 최신의 상태이며, stable 상태로 Product에 배포되는 브런치이다. 그리고 이 브런치에 대해서는 엄격한 role를 주어 사용한다.

  2. 새로운 일을 시작하기 위해 브런치를 master에서 딴다면 이름은 어떤 일을 하는지 명확하게 작성한다. git flow 와는 다르게 feature 브런치나 develop 브런치가 존재하지 않는다. 그렇기에 새로운 기능을 추가하거나 버그를 해결하기 위한 브런치의 이름은 자세하게 어떤 일을 하고 있는지에 대해서 작성해주도록 하자. Github 페이지에서 보면 어떤 일들이 진행되고 있는지를 확인하기 쉽게 말이다.

  3. 원격지 브런치로 수시로 push를 한다. git flow 와 가장 상반되는 방식이다. 항상 원격지에 자신이 하고 있는 일들을 올려 다른 사람들도 확인할 수 있도록 해준다.

이 방법의 좋은 점은 하드웨어에 문제가 발생하여 작업하던 부분이 없어지더라도 원격지에 있는 소스를 받아서 작업을 할 수 있도록 해준다.

  1. 피드백이나 도움이 필요할 때, 그리고 머징 준비가 완료되었을 때는 pull request를 생성한다. pull request 는 코드 리뷰를 도와주는 시스템이다.

그렇기에 이것을 이용하여 자신의 코드를 공유하고, 리뷰를 받을 수 있도록 한다. 물론 머지가 준비 완료되어 master 브런치로 반영을 요구하여도 된다.

  1. 기능에 대한 리뷰와 사인이 끝난 후 master로 머지한다. 곧장 product로 반영이될 기능이기에 이해관계가 연결된 사람들과 충분한 논의 이후 반영하도록 한다.

  2. master로 머지되고 푸시되었을 때는 즉시 배포되어야 한다. GitHub Flow의 핵심인듯한 master로 머지가 일어나면 hubot을 이용하여 자동으로 배포가 되도록 설정해놓는다.

장점

브런치 전략이 단순하다. 처음 git을 접하는 사람에게 정말 좋은 시스템이 된다. Github 사이트에서 제공하는 기능을 모두 사용하여 작업을 진행한다. 코드 리뷰를 자연스럽게 사용할 수 있다. CI가 필수적이며, 배포는 자동으로 진행할 수 있다. Github가 작업을 할 때 이렇게 작업하고 있다.

단점

CI와 배포 자동화가 되어있지 않은 시스템에서는 사람이 관련된 업무를 진행한다. 많은 것들이 올라오기 시작하면 굉장히 힘들어질 것이다.

브랜치 전략은 프로젝트의 특성과 팀의 작업 방식에 따라 선택해야 합니다. Git Flow는 명시적인 버전 관리가 필요한 프로젝트에 적합하고, Github Flow는 지속적 배포와 자주 릴리즈가 필요한 프로젝트에 적합합니다. 그 외에도 Gitlab Flow, Trunk-based Development와 같은 다양한 전략이 존재합니다. 시간 여유가 된다면, 이러한 전략들도 탐구해 보는 것이 좋습니다.