GitLab Flow를 통한 인싸이트
GitLab Flow를 소개하는 글의 내용이 좀 긴편이라 상단 주요 내용만 읽었다가 시간을 내 처음부터 끝까지 정독을 하였습니다.
내용이 정말 좋았는데 저에게 좋았던 몇가지 포인트를 정리하여 소개합니다.
우리 팀에 맞는 Flow를 찾아라
Git은 정말 좋은 버전 관리 도구입니다. 다양한 방법 그리고 원하는 방식으로 사용할 수 있는데 이로 인해 팀에 좋은 규칙이 없다면 복잡성과 비효율성이 매우 커지게 됩니다. 이러한 문제를 해결하기 위해 처음 제안된 것이 Git Flow입니다.
Git Flow는
- 배포 주기가 긴 경우
- 팀의 규모가 매우 크고 많은 기능을들 함께 개발하는 경우
- CI와 테스트 자동화가 안 되어 있는 경우
에 적합합니다. 하지만
- 배포 주기가 짧은 경우
- 각자 분리된 환경에서 일하는 비교적 작은 여러 팀으로 구성 된 경우
- CI와 테스트 자동화가 잘 되어 있는 경우
에는 불필요한 오버헤드가 발생하게 되며 이는 hotfix 브렌치, 별도 release로 인해 주로 발생합니다. 이를 개선하고 단순화한 것이 Github Flow, GitLab Flow입니다.
저는 속해 있는 팀들이 배포주기는 각자 다르지만 규모가 큰 편이 아니고 CI와 테스트 자동화가 어느 정도 되어 있습니다. 또 가능하면 심플한 것을 더 선호하기 때문에 Github, GitLab Flow 쪽을 더 선호합니다.
하지만 이후 팀의 상황이 변하게 되었을 때 Git Flow를 사용할 의사가 있으며 각 팀의 상황에 맞게 사용하는 것이 중요하다고 생각합니다.
Git 히스토리가 현실을 반영한다면 조금 조잡해도 괜찮아 - merge vs rebase
Git을 통한 협업 프로세스를 설계하다 보면 가능하면 Git Log를 통한 히스토리가 깔끔하게 관리되기를 원하게 됩니다.
어떻게 하면 더 깔끔하게 만들 수 있을까 고민을 많이 하게 되는데 GitLab Flow에서는 만약 Git 히스토리가 실제로 일어난 현실을 반영한다면(실제로 어떤 일이 있었는지 나중에 파악할 수 있다면) 조금 조잡해도 괜찮다고 이야기를 합니다. 별 것 아닐 수 있지만 팀 내 협업 프로세스를 고민하고 있던 저에게 큰 인싸이트를 주었습니다.
GitLab Flow에서는 이런 맥락으로 Merge, Rebase를 설명합니다.
Rebase를 기준으로 설명하면 장점은
- 별도 Merge Commit(머지 시점에 추가로 발생하는 커밋) 없이 Git 히스토리를 깔끔하게 관리할 수 있다.
- 불필요하게 나뉘어져 있거나 커밋을 하나로 합치거나 순서를 바꾸어 보기 좋은 Git 히스토리를 만들 수 있다.
는 것입니다.
단점은
- 커밋의 Author가 바뀌는 등 히스토리가 실제 작업 내용을 반영하지 못할 수 있다.
- 공유가 되어 있는 것을 Rebase 한 경우 다른 사람 로컬 레파지토리와 충돌을 일으킬 수 있다.
- PR되어 있는 것을 Rebase한 경우 지난 번 리뷰했던 것에 추가된 것을 파악하기가 힘들어진다.
는 것입니다.
Merge의 경우는 Rebase와 반대가 되겠습니다. 전부 Rebase를 쓴다거나, 전부 Merge를 하는 것은 말이 안되며 상황에 맞게 팀내 규칙을 가지고 사용해야 합니다.
더 자세한 내용은 GitLap Flow에서도 소개하고 있는 ATLASSIAN의 글을 읽어 보시기 바랍니다.
해당 글에서는 개인 Local에서 Rebase를 사용하는 것과 팀 정책으로 사용하는 것은 구분되야 한다는 것, 구체적으로 어느 경우에 Rebase를 사용하면 좋은지 등에 대한 이야기도 함께 설명하고 있습니다.
–no-ff (non fast forward) 사용 이유
Git 협업 방식 관련 여러 글들을 읽을 때 –no-ff 옵션으로 Merge를 하게 되는데 그 이유에 대한 합리적인 설명을 찾기 어려웠습니다. 어쩌면 설명이 되어 있었는데 당시에는 이해할 준비가 안되어 있어 이해를 못했을 수도 있습니다.
아무튼 오늘 글을 읽으며 –no-ff 로 Merge를 하는 주된 이유는 기능(Feature) 단위로 되돌리는 것(Revert)을 가능하도록 하기 위한 것임을 알게 되었습니다.
만약 Feature당 하나의 커밋만 허용한다면 굳이 –no-ff를 쓸 필요가 없지만 하나의 커밋만 허용하는 경우 Git 히스토리에서 볼 수 있는 정보가 제한적입니다. 또 하나의 Feature 세부 변경 사항 중 하나만 되돌리고 싶을 때에도 어쩔 수 없이 기능 자체를 되돌려야 합니다.
때문에 하나의 Feature에 유의미한 여러 커밋이 포함될 수 있도록 해야 하며, 이 것을 –no-ff로 해서 Merge Commit을 만들어 두면 각 세부 사항은 물론 해당 Feature 전체를 되돌리는 것(Revert)도 할 수 있게 됩니다.
PR을 코드 리뷰의 수단으로
하나의 기능을 개발하다보면 기능 개발이 끝나기 전에 리뷰를 받고 싶을 때가 있습니다. 이런 경우에 원격 브렌치를 상대방에게 알려주고 봐달라고 하는 경우가 많았는데, 그냥 PR을 날리면서 WIP(Work in Progress)를 제목 앞에 붙이고 이 것은 Merge가 아닌 리뷰 목적이라는 것을 팀내 규칙으로 하면 되는 일이었습니다.
이렇게 하면 보다 체계적으로 리뷰를 받을 수 있고 PR 화면에서 리뷰어가 바로 파일 수정도 할 수 있다는 장점이 있습니다.
리뷰어가 수정에 사용한 커밋은 최종 Merge 전에 Rebase하거나 Squash Merge를 해 기존 커밋에 합쳐지게 하면 됩니다.
Upstream First Policy
상위 브렌치에 우선적으로 변경사항을 반영해야 한다는 원칙입니다.
예를 들어 main 브렌치가 있고 여기에서 파생된 여러 버전별 release 브렌치(1.4-stable)가 있다고 가정했을 때, 이전 버전 release 브렌치에 버그가 발견되었다고 할지라도 우선적으로 main 브렌치에 변경 사항을 반영하고 해당 release 브렌치에 cherry pick 해야 합니다.
이렇게 해야 release 브렌치에는 반영이 되었지만 main 브렌치에는 반영이 안되는 일이 안 생깁니다.
Feature Toggle
프로젝트에 사용할 Git 협업 프로세스를 고민하다가 현재 main(GitLab Flow에서 development 역할)포함되어 있지만 아직 배포(prod 브렌치에 통합)가 되지 말아야 하는 기능들을 어떻게 처리해야 될 지 고민이 되었습니다.
GitLab Flow 설명에서 Feature Toggle을 소개하고 있는데 해당 기능을 on, off 할 수 있는 flag를 두어 해당 flag를 통해 관리를 한다는 것입니다.
Feature Branch는 5~6시간 작업량이면 좋다
Feature, Jira Ticket의 작업량을 어떻게 하면 좋을까 고민을 하고 있었는데 GitLab Flow 설명글에서 하루를 넘어가지 않도록 하는 것이 좋다고 권장하고 있었습니다.
이 것을 좀 더 구체화하면 하루에 보통 집중해서 일할 수 있는 시간이 최대 5~6시간 정도이므로 이정도 수준에서 하나의 Feature, Jira Ticket을 만들면 되겠다는 감을 잡을 수 있었습니다.