# GIT을 기반으로 한 프로젝트 개발프로세스
김지헌, <ihoneymon@gmail.com>
v0.0.1, 08-12-2015

깃을 사용합시다. 깃을 쓰자. 깃을 쓰란 말야!!

** SVN은 변경이력이 많아질수록 속도가 느리지.
*** 커밋 및 처리속도가 빠르다. 변경이력이 많이 축적되어 있어도 속도저하가 거의 없다.

** 커밋찍기가 어렵다.
+
변경사항 개발이 아직 완료되지 않았는데 이 변경사항을 중간에 커밋할 수가 없어. 커밋을 찍으면 SVN 중앙저장소에 반영되잖아.
+
*** 그런거 신경쓰지마. 맘껏 커밋을 찍어. 기능개발이 완료되면 그 때 푸시해.
*** 필요하다면 브랜치를 땋아서 거기서 개발하고 커밋찍고 개발내용을 반영하고 싶으면 병합merge하고 푸쉬해.

** 변경이력을 어떻게 봐야하지?
*** 커밋을 찍은 로그를 별도로 쉽게볼 수 있고 다양한 도구를 이용해서 확인할 수 있어.

## 깃git 이란?
> Git is a link:http://git-scm.com/about/free-and-open-source[**free and open source**] distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

깃은 크고작은 프로젝트의 모든 것들을 빠르고 효과적으로 제어할 수 있도록 설계된 **무료 그리고 오픈소스 분산형 변경이력관리시스템** 이다.

> Git is link:http://git-scm.com/documentation[**easy to learn**] and has a link:http://git-scm.com/about/small-and-fast[tiny footprint with lightning fast performance]. It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features like link:http://git-scm.com/about/branching-and-merging[cheap local branching], convenient link:http://git-scm.com/about/staging-area[staging areas], and multiple link:http://git-scm.com/about/distributed[workflows].

깃은 쉽게 배울 수 있으며 작은 크기에 비해 빛과 같은 빠른 속도를 자랑한다. 서브버전Subversion, CVS, Perforce 그리고 ClearCase 등의 기존 SCM 도구들을 능가하는 손쉬운 로컬 브랜칭, 편리한 스태징영역, 그리고 다중 업무흐름 기능을 제공한다.

link:http://git-scm.com/[git: --fast-version-control] 페이지에서 소개하는 '깃git'에 관한 설명이다. 이전의 변경이력관리도구들에 비해 훨씬 쉽고 저렴한 '브랜칭' 관리기능을 제공하여 변경이력관리에 관한 막강함을 자랑하고 있는 이 도구를 사용해보지 않겠는가?

## `git flow`을 기준으로 한 브랜치 전략
image:http://dogfeet.github.io/articles/2011/a-successful-git-branching-model/git-branching-model.png[git branch]

깃을 이용하면 '자연스레' '가지뻗기branch'하고 '커밋'하고 '병합merge'한다.

> 그 자유로운 브랜칭 사용방법에 '전략strategy'을 팀원들과 공유하여 만들고 있는 소프트웨어를 관리할 수 있다면 얼마나 좋을까?

깃플로우git-flow 전략은 소프트웨어의 소스코드를 관리하고 출시하기 위한 '브랜칭 관리 전략branch management strategy'이다. 꽤 오래전에 나온 전략이며 이 전략의 단점을 극복하기 위해 link:https://guides.github.com/introduction/flow/[github flow]와 link:https://about.gitlab.com/2014/09/29/gitlab-flow/[gitlab flow] 전략이 나왔다. 이 전략들을 그대로 적용할 수도 있지만 팀과 프로젝트 내에서 충분한 협의와 합의를 거친 후 사용하길 권한다.

우선은 기본전략이라할 수 있는 깃플로우git flow를 설명하고 깃플로우를 중심으로 하여 개발과정을 설명하여 숙달하도록 한다. 그 다음에 응용을 들어갈 수 있도록 해보자.

### 주요 브랜치
image:http://dogfeet.github.io/articles/2011/a-successful-git-branching-model/main-branches.png[main-branch]

#### *배포`master`* 브랜치
깃 사용자라면 누구나 익숙한 기본 브랜치다. 먼저 배포했거나 배포준비(production-ready)된 코드는 `origin/master`에 두고 관리한다.

`master` 브랜치에 \'병합' 한다는 것은 새버전을 배포한다는 것을 의미한다. `master` 브랜치에서 커밋될 때 git hook 스크립트를 걸어서 자동으로 빌드하여 운영서버로 배포하는 형식을 취한다.

#### *개발`develop`* 브랜치
다음에 배포하기 위해 개발하는 코드는 `origin/develop`에서 관리한다. 프로젝트를 진행하는 개발자들이 함께 보며 업무를 진행하는 브랜치이며 가장 역동적인 브랜치라고 할 수 있다. `develop` 브랜치의 코드가 안정화되고 배포할 준비가 되면 `master`로 \'병합'하고  배포버전으로 태그를 단다.

### 보조브랜치
배포를 준비하고, 이미 배포한 제품이나 서비스의 버그를 빠르게 해결(hotfix) 해야한다. 이 모든 것을 동시에 진행하기 위해서 다양한 브랜치가 필요하다.

#### *기능feature* 브랜치
[NOTE]
.기능 브랜치
===============================================================
* 시작브랜치: `develop`
* 병합대상 브랜치: `develop`
* 브랜치이름 규칙: `master`, `develop`, `release-*`, `hotfix-*` 를 제외한 것
===============================================================
image:http://dogfeet.github.io/articles/2011/a-successful-git-branching-model/merge-without-ff.png[git merge --no-ff]

기능`feature` 브랜치는 배포하려고 하는 **기능을 개발하는 브랜치**다. 기능을 개발하기 시작할 때는 언제 배포할 수 있을지 알 수 없다.  프로젝트를 진행하면서 애자일 방법론을 도입했다면, 스프린트 기간 동안에 개발해야할 기능이라면 스프린트 기간동안 개발해야할 브랜치를 말한다. 기능`feature` 브랜치는 그 기능을 다 완성할 때까지 유지하고 있다가 다 완성되면 개발`develop` 브랜치로 병합한다. 개발된 결과가 실망스럽거나 필요없을 때는 삭제하면 된다. 삭제하는 것에 미련을 가질 필요는 없다.

** git-flow 이용시 `feature/{branch-name}` 형식
** 이슈추적을 사용한다면 `feature/{issue-number}-{feature-name}` 형식
*** Ex) feature/1-init-project, feature/2-build-gradle-script-write

#### *출시release* 브랜치
[NOTE]
.출시 브랜치
===============================================================
* 시작브랜치: `develop`
* 병합대상 브랜치: `develop`, `master`
* 브랜치이름 규칙: `release-*`
===============================================================

출시`release` 브랜치는 실제 배포할 상태가 된 경우에 생성하는 브랜치다. 마스터`master` 브랜치를 통해 배포하기로 했으므로 먼저 출시`release`를 마스터`master` 브랜치로 병합한다. 나중에 이 배포버전을 찾기 쉽도록 태그를 만들어 현재 병합되는 커밋을 가리키도록 한다. 이 때 배포된 기능에 반영될 수 있도록 개발`develop` 브랜치에도 함께 병합한다.

#### *긴급수정hotfix* 브랜치
[NOTE]
.긴급수정 브랜치
===============================================================
* 시작브랜치: `master`
* 병합대상 브랜치: `develop`, `master`
* 브랜치이름 규칙: `hotfix-*`
===============================================================
image:http://dogfeet.github.io/articles/2011/a-successful-git-branching-model/hotfix-branches.png[hotfix branch]

미리 계획되지 않은 배포를 위한 브랜치다. 기본적인 동작방식은 출시`release`와 비슷하다. 이미 배포한 운영버전에서 발생한 문제를 해결하기 위해 만든다. 운영 버전에 생긴 치명적인 버그는 즉시 해결해야하기 때문에 문제가 생기면 마스터`master` 브랜치에 만들어둔 태그`tag`로부터 긴급수정`hotfix` 브랜치를 생성한다.

## 개발과정을 기준으로 한 깃 사용방법 설명
윈도우와 맥에서 사용할 수 있는 깃클라이언트로 많이 사용되는 link:https://www.sourcetreeapp.com/[소스트리sourceTree]를 기준으로 진행한다.

### 사전 확인사항
. 깃설정에서 \'**사용자명**'과 \'**이메일**' 정보가 입력되어 있는지 확인한다.
. 깃 저장소에 `master` 브랜치가 존재해야 한다.

### git flow 시작하기
. 저장소 선택 후 [깃 플로우] 버튼 클릭
+
.[깃 플로우] 버튼 클릭
image::./git-flow-001.png[Click git flow button]
+

. 깃플로우 목적별 브랜치 초기설정
+
image::./git-flow-002.png[git flow configuration]
+

. 깃플로우 생성
+
image::./git-flow-004.png[git flow init]
+

. 깃플로우 초기화 완료
+
image::./git-flow-005.png[git flow init complete]
+
깃플로우 초기화가 완료되면 `develop` 브랜치가 생성되어 체크아웃 상태가 되어 있다.

### 기능개발
다음과 같은 '74. 빌드'와 관련된 기능을 개발해야 한다고 가정해보자.
image::./git-flow-feature-001.png[TiDD]

#### *기능feature* 브랜치 생성
. 깃플로우버튼 클릭
. [새 기능 시작] 버튼을 클릭한다.
+
.[새 기능 시작] 버튼 클릭
image::./git-flow-feature-002.png[Click new feature branch]
+

. 기능명 입력후 [확인] 클릭
+
.feature branch name: 74-build
image::./git-flow-feature-003.png[new feature branch name]
+
.. 기능브랜치의 이름은 `[issue number]-[기능명 혹은 기능 서술]` 형태면 좋다.

. 기능브랜치가 생성된 것 확인
+
.feature branch complete
image::./git-flow-feature-004.png[feature/74-build branching complete]
+


#### *기능feature* 브랜치 내에서 커밋
커밋메시지에는 현재 개발하고 있는 기능과 관련된 이슈번호를 함께 넣어주는 것이 좋다. 커밋메시지에서 `# 메시지`의 경우에는 주석으로 인식하지만 `#이슈번호` 인 경우에는 깃 저장소 개발플랫폼에 따라 이슈와 연결시켜준다.

.commit message on feature branch
image::./git-flow-feature-005.png[commit message bind issue number]


> 깃메시지는 메시지만으로 해당 커밋에서 수행한 항목들을 이해할 수 있도록 설명하는 것이 좋고, 기능개발과정 중간중간 테스트를 통과시킨 후 커밋을 찍도록 한다.


#### *기능feature* 브랜치 완료
기능 개발이 완료되었다면,

. [깃 플로우 버튼] 클릭
. [기능 마무리] 클릭
+
.[기능 마무리] 버튼 클릭
image::./git-flow-feature-006.png[기능 마무리]
+


. \'기능 마무리' 항목에서 [확인] 버튼 클릭
+
.[확인] 클릭
image::./git-flow-feature-007.png[확인]
.feature 브랜치 완료화면
image::./git-flow-feature-008.png[feature branch complete]
+

.. \'develop 브랜치에 rebase'는 클릭하지 않는다.
... 개발자가 기능브랜치를 생성하여 작업한 이력을 남길 수 있어 추후 변경이력을 추적하는데 용이하다.
+
.rebase를 사용하지 않은 브랜치모습
image::./git-flow-feature-009.png[not use rebase]
+


### 출시
애플리케이션을 배포할 때가 되었다.

#### *출시release* 브랜치 생성
. [깃플로우] 버튼 클릭
. [새 릴리즈 시작] 버튼 클릭
+
.[새 릴리즈 시작] 버튼 클릭
image::./git-flow-release-001.png[Click new release]
+

. 출시버전 입력 후 [확인] 버튼 클릭
+
.출시버전 입력
image::./git-flow-release-002.png[input release version]
.출시브랜치 생성명령 실행화면
image::./git-flow-release-003.png[create release branch]
+

. 출시버전 브랜치 생성확인
+
.출시버전 브랜치 생성확인
image::./git-flow-release-004.png[release branch complete]
+


#### 출시에 필요한 기능들 합치기
출시 브랜치를 생성한 후에 기능을 추가적으로 개발한 경우들이 발생할 수 있다. 그럴 경우에는 기능개발을 완료하고 `develop` 브랜치에 병합한 후에 `develop` 브랜치를 출시 브랜치로 병합하면 되겠다.

#### *출시release* 브랜치 완료
. [깃 플로우] 버튼 클릭
. [릴리즈 마무리] 버튼 클릭
+
.[릴리즈 마무리] 버튼 클릭
image::./git-flow-release-005.png[Click release finish]
+

. \'릴리즈 마무리' [확인] 클릭
+
.\'릴리즈 마무리' [확인] 클릭
image::./git-flow-release-006.png[click confirm]
+


### *긴급수정hotfix* 브랜치
출시이후 긴급수정해야할 내용이 발생하는 경우 출시버전에 맞춰서 핫픽스를 생성한다.

#### *긴급수정hotfix* 브랜치 생성
. [깃 플로우] 버튼 클릭
. [새 핫픽스 시작] 버튼 클릭
+
.[새 핫픽스 시작] 버튼 클릭
image::./git-flow-hotfix-001.png[click new hotfix]
+

. 핫픽스이름 입력 후 [확인]
+
.핫픽스이름 입력 후 [확인]
image::./git-flow-hotfix-002.png[hotfix name]
+


#### *긴급수정hotfix* 작업진행

#### *긴급수정hotfix* 브랜치 완료
. [깃 플로우] 버튼 클릭
. [핫픽스 마무리] 버튼 클릭
+
.[핫픽스 마무리] 버튼 클릭
image::./git-flow-hotfix-003.png[hotfix finish]
+

. \'핫픽스 마무리' [확인] 버튼 클릭
+
.\'핫픽스 마무리' [확인] 버튼 클릭
image::./git-flow-hotfix-004.png[hotfix complete]
+

. 긴급수정 브랜치 처리 완료
+
.긴급수정 브랜치 처리 완료 실행기록
image::./git-flow-hotfix-005.png[hotfix log]
.긴급수정 브랜치 처리 완료후
image::./git-flow-hotfix-006.png[hotfix complete]
+


### 프로젝트 참여자들 강요사항
* 개발, 변경사항에 대한 테스트 통과 후 커밋을 찍고 밀어넣는다.

## 로컬-개발서버-테스트서버-운영서버 전략
* 로컬, 개발서버는 개발`develop`브랜치를 기준으로 빌드-배포한다.
* 테스트-운영서버는 마스터`master` 브랜치를 기준으로 빌드-배포한다.

### 브랜치 이용 관리전략
* 프로젝트에 참여중인 개발자들은 개발`develop` 브랜치를 기준으로 업무를 진행한다.
* 마스터`master` 브랜치는 아키텍트, 프로젝트리더 혹은 선임개발자가 관리한다.
* 사전에 협의되지 않은 내용은 마스터`master` 브랜치에 반영하지 않는다.

## 정리
깃플로우`git flow`는 깃에서 제공하는 강력한 브랜칭 기능을 활용한 변경이력 관리 전략이다. 이 전략은 상황에 따라서 다양한 변화가 가능하다. 깃플로우는 다양한 변형된 형태의 전략을 세울수 있으며 깃헙github, 깃랩gitlab 에서 제공하는 방식이 있다.

> 중요한 것은 팀원, 프로젝트 구성원이 깃플로우 전략에 대해서 숙지하고 어떻게 사용할지를 결정하여 함께 공유하고 있어야 한다는 것이다.

> 깃이 제공하는 손쉬운 브랜치생성 기능을 활용하자.

## 참고문헌
* link:http://dogfeet.github.io/articles/2011/a-successful-git-branching-model.html[A successful git branching model]
* github flow
+
Release가 분명하지 않은 경우엔 확실히 git-flow를 적용하기 어렵다. - 이것이 깃플로우가 가지고 있는 단점!
+
** link:https://guides.github.com/introduction/flow/[Introduction github flow]
** link:https://dogfeet.github.io/articles/2011/github-flow.html[github flow]
* gitlab flow
** link:https://about.gitlab.com/2014/09/29/gitlab-flow/[gitlab flow]