[Git] 깃 플로우(Git Flow)란?
깃을 효과적으로 사용하는 방법을 찾아보다가 동료 개발자의 추천으로 배민 기술 블로그의 깃 플로우 포스팅을 접했다.
https://techblog.woowahan.com/2553/
읽어보고 이렇게 사용하면 현업에서 많은 도움이 될 것 같았고, 실제로 모든 개발자들이 이렇게 쓰지 않을까도 생각했다. 그래서 깃 플로우가 무엇인지 정의부터 알아가기로 했다.
먼저 Flow는 사전적 정의가 "흐름, 유출량, 공급량" 등이라, 뭔가가 움직인다는 뉘앙스의 단어라고 생각한다. 그래서 처음 깃 플로우란 단어를 보고 든 생각은 깃으로 소스코드들을 제어해서(또는 이동시켜) 관리하는 프로그램이나 방법론이지 않을까 생각했다. 이 가설을 토대로 깃 플로우가 무엇인지 찾아봤다.
https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
GitFlow는 원래 깃 브랜치 관리를 위한 전략이었던 Git Workflow다. GitFlow는 이제 최신 지속적인 소프트웨어 개발 및 Devops 사례를 위한 권장사항으로 간주되는 트렁크 기반 워크플로우를 선호하여 인기가 떨어졌다. GitFlow는 또한 CI/CD와 함께 사용하기 어려울 수 있다...(중략)...GitFlow는 feature 브랜치와 여러 기본(primary) 브랜치를 사용하는 대안적인 Git 브랜치 모델이다. nvie에서 Vincent Driessen에 의해 처음 대중화됐다. 트렁크 기반 개발과 비교할 때 GitFlow에는 더 오래 지속되는 수많은 브랜치와 더 큰 커밋이 있다. 이 모델에서 개발자는 feature 브랜치를 만들고 기능이 완료될 때까지 이를 기본 트렁크 분기에 병합(merge)하는 것을 연기한다. 이러한 수명이 긴 feature 브랜치는 병합하기 위해 더 많은 협업이 필요하고, 트렁크 분기에서 벗어날 위험이 더 높다. 충돌하는 업데이트를 도입할 수도 있다. GitFlow는 예정된 출시 주기가 있는 프로젝트와 지속적 제공의 DevOps 모범 사례에 사용할 수 있다. 이 워크플로우는 feature 브랜치 워크플로우에 필요한 것 이상으로 새 개념이나 명령을 추가하지 않는다. 대신 매우 구체적인 역할을 다른 브랜치에 할당하고 상호 작용 방법과 시기를 정의한다. feature 브랜치 외에도 release 준비, 유지관리 및 기록을 위해 개별 브랜치를 사용한다. 물론 풀 리퀘스트, 격리된 실험(isolated experiments), 더 효율적인 협업 등 feature 브랜치 워크플로우의 모든 이점을 활용할 수도 있다
https://dahye-jeong.gitbook.io/git/git/2019-01-27-git-flow
git-flow는 Vincent Driessen의 branching model을 적용해 고수준으로 저장소를 관리할 수 있게 해주는 확장 기능이다. branching model은 feature - develop(dev) - release - hotfix - master 단계로 브랜치를 나눠 코드를 관리하는 전략이며 사용자가 쉽게 접근하고 사용할 수 있도록 확장 기능(명령어)을 제공하는 것이다. git-flow에는 5가지 브랜치가 있다. 항상 유지되는 주요 브랜치들(master, develop)과 일정 기간 동안만 유지되는 보조 브랜치들(feature, release, hotfix)이 있다
https://chanyeong.com/blog/post/15
GitFlow는 Git을 사용한 개발 작업 절차다. 프로그램이 아닌 약속, 규칙 같은 개념이다. Vincent Driessen 또한 GitFlow는 완벽한 방법론이 아닌 각자 팀에 맞는 개발 환경에 따라 변형해 사용하는 게 좋다고 언급했다
정리하면 깃 플로우는 프로그램이 아니라 개발자끼리 지키는 하나의 개발 원칙같은 것이다.
웹, 앱 등 어떤 프로그램을 만들 때 개발자들끼리 깃 플로우를 어떤 형태로 쓸지 논의해 결정하면 그대로 따르되, 그 환경이 깃일 뿐이라고 이해했다.
그럼 깃 플로우의 장점은 무엇이 있을까? 검색하다가 괜찮아 보이는 글을 찾아 인용한다.
https://datasift.github.io/gitflow/IntroducingGitFlow.html
병렬 개발 : 깃 플로우의 장점 중 하나는 완료된 작업에서 새 개발을 분리해 병렬 개발을 매우 쉽게 만든다는 것이다. 새 개발(기능 및 긴급하지 않은 버그 수정)은 feature 브랜치에서 수행되며 개발자가 코드를 릴리즈할 준비가 되었다고 생각할 때만 코드 본문에 다시 병합된다. 중단은 BadThing(tm)이지만 한 작업에서 다른 작업으로 전환하라는 메시지가 표시되면 변경사항을 커밋한 뒤에 새 작업에 대한 새 feature 브랜치를 만들기만 하면 된다. 해당 작업이 완료되면 원래의 feature 브랜치를 checkout하고 중단한 부분부터 계속할 수 있다
협업 : feature 브랜치를 쓰면 둘 이상의 개발자가 같은 기능에 대해 더 쉽게 공동 작업을 할 수 있다. 각 feature 브랜치는 새 기능을 작동시키는 데 필요한 변경사항만 변경되는 샌드박스기 때문이다. 따라서 각 공동 작업자가 수행하는 작업을 매우 쉽게 보고 따라할 수 있다
릴리즈 스테이징 영역 : 새 개발이 끝나면 아직 출시되지 않은 완성된 기능들을 위한 준비영역인 develop 브랜치로 다시 병합된다. 따라서 다음 릴리스가 develop에서 분기되면 완료된 모든 새 항목이 자동 포함된다
긴급 수정 지원 : 깃 플로우는 hotfix 브랜치(태그가 지정된 릴리스에서 만든 브랜치)를 지원한다. hotfix에선 긴급 수정 사항만 포함돼 있으므로 이를 사용해 긴급 변경을 수행할 수 있다. 동시에 새 개발에 실수로 병합할 위험이 없다
https://bjurr.com/gitflow-and-when-you-should-use-it/
...(중략)...개발자가 다음 릴리스에서 작업하는 걸 방해하지 않으면서 코드를 정지할 수 있다. 브랜치 없이 matser에서 릴리스만 실행하면 해당 프로세스를 쉽게 자동화할 수 있다. release 브랜치를 만들고 결국 다시 master로 병합, 개발해야 하는 경우 더 복잡한 흐름(flow)이 필요하다
장점만 놓고 보면 개발자라면 안 쓸 이유가 없어 보인다. 어느 선까지 프로그램을 개발해서 출시한 이후에도 자유롭게 새 기능을 추가할 수 있고, 한 프로그램에 여러 개발자가 붙어서 작업할 수도 있다. 이렇게 완벽한 방법론이 있었구나 라고 생각했지만 장점을 말하는 사람이 있으면 단점을 말하는 사람도 있는 법이다.
https://georgestocker.com/2020/03/04/please-stop-recommending-git-flow/
마이크로서비스 또는 지속적 전달에 대해 생각하기 전에도 깃 플로우는 복잡하다. 아래 사진을 보자마자 직관적이라고 말할 수 있는가?
여기에 feature, release, master, develop, hotfix 브랜치 및 Git 태그가 있다. 이는 빌드 및 릴리스 프로세스에서 추적, 이해, 설명돼야 하는 모든 것이다. 뿐만 아니라 항상 어떤 브랜치가 무엇인지 추적해야 한다. 이것이 유용하기 위해 유지해야 하는 mental model은 높은 인지 부하를 수반한다
- GitFlow는 브랜치의 "단명(Short-lived)" 원칙을 위반한다 : 깃에서 브랜치에 커밋하는 사람들과의 병합 충돌 개수는 해당 브랜치에서 작업하는 사람 수에 따라 증가한다. GitFlow를 쓰면 feature, release, hotfix 브랜치 등 다른 브랜치가 develop으로 병합되기 때문에 그 수가 훨씬 더 증가한다. 따라서 이제 병합 충돌 가능성은 선형이 아니며 잠재적으로 3배 증가한다. 병합 충돌에 대한 걱정이라고 말하길 주저하지만 GitFlow와 같은 브랜치 전략을 추구하지 않는 타당한 이유다. 이런 모든 브랜치가 모일 때 도입되는 잠재적 복잡성의 양은 너무 커서 간과할 수 없다. 커밋 속도 비율이 낮은 조직의 경우엔 적합하지만, 빠르게 움직일 수 있는 조직이나 스타트업의 경우 그렇지 않다
- GitFlow는 rebase를 포기한다 : GitFlow를 추구한다면 rebase를 포기해야 할 것이다. rebase하면 병합 커밋이 사라진다는 걸 기억하라. 두 브랜치가 함께 오는 걸 볼 수 있는 지점이다. 그리고 GitFlow의 시각적 복잡성으로 인해 브랜치를 시각적으로 추적해야 하므로 문제를 풀고 싶다면 rebase가 불필요하다
- GitFlow는 여러 레포에서 작업할 수 있다 : 개별 팀이 자신의 레포와 워크플로우를 제어하고 체크인할 사람을 제어할 수 있는 마이크로 레포지토리에 대한 아이디어도 더 많이 추진되었다. 저장소 및 워크플로우의 작동 방식, 여러 팀과 함께 GitFlow 같은 복잡한 브랜치 모델을 시도하고 모든 사람이 같은 페이지에 있기를 희망한 적이 있는가? 불가능하다. 시스템은 곧 다양한 레포지토리의 다양한 개정판의 매니페스트가 되며 모든 것이 어디 있는지 아는 유일한 사람은 매니페스트를 업데이트하기 위해 YAML을 만드는 사람들 뿐이다
- GitFlow는 monorepo에서도 작업이 불가능하다 : 릴리스 조정의 어려움으로 마이크로 레포지토리가 없는 경우 모든 마이크로서비스 팀이 릴리스를 위해 준수해야 하는 하나의 큰 브랜치 워크플로우가 아닌 이유는 무엇인가? 다른 팀이 자기 컨텐츠를 출시할 준비가 안 됐을 때, 팀이 독립적이고 마이크로서비스를 독립적으로 배포할 수 있어야 하는 경우 모노 레포지토리에서 생성한 중앙 집중식 브랜치 모델에 워크플로우를 잘 연결할 수 없다
https://codeburst.io/trunk-based-development-vs-git-flow-a0212a6cae64
GitFlow의 장점 중 하나는 엄격한 제어다. 승인된 개발자만 변경 사항을 자세히 검토한 후 승인할 수 있다. 코드 품질을 보장하고 버그의 조기 제어에 도움이 된다. 그러나 이것이 큰 단점이 될 수도 있음을 알아야 한다. 깔때기를 만들어 개발 속도를 늦춘다. 속도가 주요 관심사라면 심각한 문제일 수 있다. 별도 개발된 기능은 메인 프로젝트와 결합하기 어려울 수 있는 오래 지속되는 브랜치를 만들 수 있다. 또한 Pull request는 새 코드에만 코드 검토를 집중한다. 코드를 전체적으로 보고 개선하기 위해 노력하는 대신 새로 도입된 변경사항만 확인한다...(중략)...Pull request는 리드 개발자가 말 그대로 모든 코드를 관리하는 광범위한 마이크로 관리로 이어질 수 있다
정리하면 깃 플로우를 써서 내가 얻는 장점은
- 승인된 개발자만 코드에 접근할 수 있게 해서 안전하게 소스코드를 관리할 수 있다
- 출시된 프로그램의 코드를 안전하게 수정, 병합할 수 있다
- feature 브랜치, 풀 리퀘스트를 활용해서 새 기능 개발에 집중할 수 있다
이 3가지인데, 직접 사용해 본 결과 처음에 많이 헤맸다.
main 브랜치를 건드리지 않고 develop 브랜치에서 feature 브랜치를 만들고, 개발이 끝나면 develop에 병합하는 과정 자체가 애매했다. 새 레포를 하나 만들고 계속 연습하고 나니 어느정도 손에 익긴 했다.
이 글을 보고 Git Flow를 적용할 사람은 Git Bash 등에서 명령어로 작업하는 건 리눅스를 써본 적 없다면 어려울 수 있으니 처음엔 GUI 프로그램을 써서 하는 게 나을 것 같다.