[Git 원데이] Git-flow
1. Git-flow
1) Git-flow 란?
일반적인 개발 프로세스는 '기획-디자인-개발-QA-출시' 순으로 진행되며 주기적으로 앱을 출시 한다. 기획, 디자인, 서버 등 협업하는 인원들과 흐름을 맞춰서 진행하기 때문에 많은 인원이 이번 버전에 포함될 기능을 개발하는 것은 비효율적이게 된다.
따라서 우선순위에 따라 나열한 작업 중 우선순위가 높은 작업부터 선택하여 작업을 분담하고, 이번 버전에 포함될 필수 작업과 추후에 배포될 작업들을 병렬로 진행한다. 병렬로 처리하던 작업들이 완료되면, 가까운 배포 주기에 포함시켜 출시를 진행한다. 이러한 개발 프로세스를 잘 녹여내기 위한 모델로는 Git-flow가 있다.
처음 시작에는 master와 develop 브랜치가 존재한다. develop 브랜치는 master에서부터 시작된 브랜치이다. develop 브랜치에서는 상시로 버그를 수정한 커밋들이 추가가 된다.
새로운 기능 추가 작업이 있는 경우 develop 브랜치에서 feature 브랜치를 생성한다. feature 브랜치는 항상 develop 브랜치에서 시작한다. 기능 추가 작업이 완료될 경우 feature 브랜치는 develop 브랜치로 merge 된다.
develop에 이번 버전에 포함되는 모든 기능이 merge 되었을 경우 QA를 하기 위해 develop 브랜치에서부터 release 브랜치를 생성한다. QA를 진행하면서 발생한 버그들은 release 브랜치에 수정된다.
QA를 무사히 통과할 경우 release 브랜치를 master와 develop 브랜치로 merge 한다. 마지막으로 출시된 master 브랜치에서 버전 태그를 추가한다.
2) IntelliJ 플러그인
대부분의 회사에서 Git을 사용할 경우 Git Flow를 따른다. 하지만 브랜치를 스위칭하는 과정에서 번거롭기에 더 편하게 관리할 수 있도록 다양한 플러그인이 존재한다. IntelliJ를 기준으로 'Git Flow Integration' 플러그인을 설치하여 이용이 가능하다.
해당 플러그인을 사용하기 전에, Homebrew를 이용하여 git flow를 먼저 설치를 진행한다.
brew install git-flow-avh
3) 테스트
깃 허브에 테스트용 레포지토리를 생성해주고 클론을 받아 IntelliJ로 열어준다. Sourcetree 처럼 Git graph를 확인하려면 맥 기준 'Command + 9'로 확인할 수 있다.
Git flow를 초기화해준다.
새로운 기능을 추가하기 위해 하단에서 'Start Feature'를 선택하고 새로운 기능에 대한 이름을 입력해준다. 이 후 로그를 확인을 해보면 'feature/add-file1'이 추가가 되는 것을 확인할 수 있다.
다음으로는 'feature/add-file1' 브랜치에서 'file1'을 임의로 생성해주고 커밋을 해준다.
다시 develop 브랜치로 돌아와서(checkout) 새로운 기능을 위한 브랜치를 추가해준다. file2라는 임의의 파일을 생성하고 커밋을 진행해준뒤 'Finish Feature' - 기능을 마무리했다는 항목을 선택해준다.
기능을 마무리를 한 결과로는 'feature/add-file2'의 브랜치가 삭제가 되고, develop 브랜치에 병합이 되는 것을 확인할 수 있다.
마찬가지로 'feature/add-file1' 브랜치로 이동하여 'Finish Feature'로 해당 브랜치를 삭제함과 동시에 develop 브랜치에 합병해준다.
다음으로 처리해주어야 하는 것은 release 이다. release는 주로 버전을 입력해준다. 해당 브랜치에서 테스트를 진행해보고 테스트가 정상적으로 끝났으면 그걸 main 브랜치에도 합병을 해준다. 이를 위해 'Finish Release' 항목을 선택해준다.
'Finish Release'에서 tag message는 배포할 때 브랜치 이름 대신으로 사용할 수 있다.
4) Pull Request
테스트를 한 환경에서 develop 브랜치를 Push 해준다. 'feature/add-file3'라는 이름의 브랜치를 새로 생성해준다. 위와 동일하게 새로운 파일을 생성해주고 커밋을 해준다.
원격지로 Push 해준다.
'feature/add-file3' 브랜치와 develop 브랜치를 합병하려고 할 때, Pull Request를 이용한다.
Pull requests 항목에 들어가 'New pull request'를 선택한다.
그리고 무엇을 어디로 합병시킬지에 대한 설정을 해준다. ('feature/add-file3'에서 develop 브랜치로)
Create Pull Request를 선택하면 Open a pull request 화면이 나오게 되는데, 여기서 리뷰를 할 사람과 누가 합병을 할 수 있는지에 대한 정보를 넣어준다. (혼자서 하는 테스트이기에 리뷰에는 공란, 머지할 사람은 나 자신을 넣어준다.)
그 결과로 Open 상태와 어디에서 어디로 합병이 되는지에 대한 정보를 확인할 수 있다. 여기서 Pull Request에 대해서 해줄 수 있는 액션으로는 크게 두 가지가 존재한다.
- Pull Request를 잘못 보냈을 경우, 하단의 'Close Pull Request' 선택하는 액션
- Pull Request를 합병하는 경우 'Merge Pull request' 선택하는 액션
우선 Merge를 진행하고, 다시 IntelliJ로 돌아와 develop 브랜치로 돌아가서 pull을 받아준다.
Merge Pull request에도 3가지 방법이 존재한다.
- Merge
a, b, c를 refer 하는 m 커밋 노드 생성한다. m은 parent로 init, c를 가진다.
커밋 m에서부터 뒤로 되돌아가면서 부모를 모두 찾아 브랜치를 구성한다. 커밋 m은 부모로 c와 init을 가지고 있으며 c는 b를, b는 a를, a는 init을 다시 부모로 가진다. 이형상을 모두 backtrace하여 'init - a - b - c - m'의 구조를 만들고 이 구조가 모두 히스토리에 남는다.
- Squash And Merge
a, b, c를 합쳐 새로운 커밋으로 만들고, 합병 대상 브랜치에 추가한다. 'a, b, c' 커밋은 parent를 init 하나만 가진다.
커밋 a, b, c는 init만을 부모로 가진 단일 커밋이다. 작업했던 a, b, c 커밋들은 합병 후의 메인 브랜치 커밋 init과 'a,b,c'와 아무런 연관을 가지지 않는다.
- Rebase and Merge
a, b, c를 심리스하게 합병 대상 브랜치로 추가한다. 각 커밋들은 모두 parent를 하나씩만 가진다.
커밋 a, b, c의 관계를 그대로 유지한 채 메인 브랜치에 그대로 추가한다. 커밋 a는 부모로 커밋 e를 가진다. Rebase and Merge 작업 후에는 작업했던 브랜치의 a, b, c 커밋들은 합병 후의 메인 브랜치의 init, d, e, a, b, c, 커밋들과 연관 관계를 가지지 않는다.
develop-feature 브랜치간의 합병에는 Squash and Merge가 유용하다. 지저분한 feature의 히스토리를 모두 묶어 완전 새로운 커밋으로 develop 브랜치에 추가하여 develop 브랜치에서 독자적으로 관리할 수 있기 때문이다. 일반적으로 합병 후에 feature 브랜치를 삭제하는 경우, feature 브랜치의 커밋 히스토리를 모두 develop 브랜치에 직접 연관 지어 남길 필요가 없다.
master-develop 브랜치간의 합병에는 Rebase and Merge가 유용하다. develop의 내용을 master에 추가할 때에는 별도의 새로운 커밋을 생성할 이유가 없기 때문이다.
hotfix-develop, hotfix-master 브랜치간의 합병은 Merge 혹은 Squash and Merge 모두 유용하다. hotfix 브랜치 작업의 각 커밋 히스토리가 모두 남아야하는 경우 Merge를, 필요 없는 경우 Squash and Merge를 사용한다.
5) Commit 수정
위와 동일한 과정으로 'feature/add-file4' 브랜치를 생성하여 파일을 생성해준다. 그리고 커밋을 해주는데, 만약 커밋 메시지를 잘못입력했을 때에는 IntelliJ의 그래프에서 'Undo Commit' 항목을 선택해주면 된다.
만약 이미 서버에 Push를 한 상태에서 마지막 커밋을 수정하기 위해서는 마지막 커밋을 수정한 뒤 절대 브랜치를 바꾸지 않은 상태에서 터미널에 'git push -f' 명령어를 입력해준다. 이 명령어는 강제로 기존 커밋이 지워지고 새로 수정한 커밋이 서버에 반영되도록 해준다. 하지만 강제로 현재 브랜치 상태로 저장소에 Push하는 것이기 때문에 주의가 필요하다.
6) Cherry Pick
새로운 'feature/add-files' 브랜치를 만든다. 이 후 파일을 생성하고 커밋하는 과정을 5번 수행해준다. 다음으로 develop으로 돌아가 원하는 커밋(file6)만을 붙일 수 있도록, Cherry Pick을 해준다.
7) Task 기능과 함께 사용
주로 IntelliJ가 제공하는 Task 기능과 사용하기도 한다.
2. 요약
Git-flow는 Vincent Driessen이 제안한 깃의 workflow 디자인에 기반한 브랜칭 모델이다. Vincent는 master, develop, feature, release, hotfix 5개 종류의 branch로 나눠서 관리한다.
브랜치 | 설명 |
feature | 어떤 새로운 기능이 추가되어야 할 때 사용되는 브랜치이다. 개발이 완료되면 parent인 develop 브랜치로 merge된다. master 브랜치에는 직접적으로 접근할 수 없다. |
develop | develop 브랜치는 product로 release를 할 준비가 된 가장 안정적인 브랜치이다. 즉, master로 merge 하기 전 개발된 모든 feature가 develop에 merge된다. |
release | develop 브랜치에서 어느 정도 feature들을 merge 하고 release 해야겠다 생각될 때 생성하는 브랜치이다. develop 브랜치에서 release 브랜치로 merge하고 release가 완료되면 다음 release 브랜치 사이클을 진행한다. |
hotfix | release된 product에서 발생한 버그 같은 것을 수정해야 할 때 사용되는 브랜치이다. 수정이 완료된 후에는 수정사항을 반영하기 위해 master와 develop branch 모두 merge 한다. |
master | 가장 코어가 되는 브랜치는 master와 develop이다. 그 중 master는 product로 release하는 브랜치이다. 결국 모든 변경사항은 master로 merge되어야 한다. |
- master - 제품으로 출시될 수 있는 브랜치
- develop - 다음 출시 버전을 개발하는 브랜치
- feature - 기능을 개발하는 브랜치
- release - 이번 출시 버전을 준비하는 브랜치
- hotfix - 출시 버전에서 발생한 버그를 수정하는 브랜치
전체적인 흐름은 다음과 같다.
- develop 브랜치에서 시작
- develop 브랜치를 기반으로 feature 브랜치를 생성하여 새 기능을 개발
- feature 브랜치에서 개발 완료 시 develop에 병합
- 기능을 공동으로 개발하고 있다면 원격 서버에 기능을 게시하고, 다른 사용자가 게시한 기능을 가져오기
- 새로운 제품 출시를 위한 준비(사소한 버그 수정, 메타 데이터 준비)로 develop 브랜치에서 release 브랜치 생성
- 릴리스가 완료될 경우 release 브랜치를 master 브랜치에 병합, 릴리스를 릴리스 이름으로 태그, 릴리스를 develop 브랜치에 병합 release 브랜치 삭제
hotfix의 경우 현재 출시된 제품에 문제가 생겨서 즉각 대응해야하는 상황에 사용한다.
- master 브랜치의 현재 출시된 버전으로 표기된 태그로부터 브랜치를 따고 hotfix 종료 시 develop과 master 브랜치에 병합
Pull Request 합병하는 방법은 다음과 같다.
- develop-feature 브랜치간의 합병에는 Squash and Merge
- master-develop 브랜치간의 합병에는 Rebase and Merge
- hotfix-develop, hotfix-master 브랜치간의 합병은 Merge 혹은 Squash and Merge
[참고] meetup.toast.com/posts/122
[참고] www.holaxprogramming.com/2018/11/01/git-commands/
[참고] danielkummer.github.io/git-flow-cheatsheet/index.ko_KR.html
[참고] woowabros.github.io/experience/2017/10/30/baemin-mobile-git-branch-strategy.html