본문 바로가기
Book Study/Pro Git

[Pro Git] ch03 - Git 브랜치 2 (Workflow)

by 랩린안 2022. 10. 3.

출처 : Pro Git (p93 ~116p)

- 저자 : Scott Chacon, Ben Straub

 

기존에 헷갈리던 게 이해가 된 부분만 기록합니다. 중간에 비어있는 부분들이 있습니다.

빨간글씨로 보충 설명을 적습니다. 정확하지 않을 수 있습니다.

 

아마 3장 브랜치까지만 읽고 다음 장부터는 천천히 읽게 될 거 같다. 

 

 


 

브랜치 Workflow

브랜치를 만들고 Merge 하는 것을 어디에 써먹어야 할까. 이 절에서는 Git 브 랜치가 유용한 몇 가지 Workflow를 살펴본다. 여기서 설명하는 Workflow를 개발에 적용하면 도움이 될 것이다.

 

워크플로는 작업 절차를 통한 정보 또는 업무의 이동을 의미하며, 작업 흐름이라고도 부른다. 더 자세히 말해, 워크플로는 작업 절차의 운영적 측면

 

Long-Running 브랜치

Git은 꼼꼼하게 3-way Merge를 사용하기 때문에 장기간에 걸쳐서 한 브랜 치를 다른 브랜치와 여러 번 Merge 하는 것이 쉬운 편이다. 그래서 개발 과정 에서 필요한 용도에 따라 브랜치를 만들어 두고 계속 사용할 수 있다. 그리고 정기적으로 브랜치를 다른 브랜치로 Merge 한다.

 

이런 접근법에 따라서 Git 개발자가 많이 선호하는 Workflow가 하나 있다. 배포했거나 배포할 코드만 master 브랜치에 Merge 해서 안정 버전의 코드만 master 브랜치에 둔다. 개발을 진행하고 안정화하는 브랜치는 develop이나 next라는 이름으로 추가로 만들어 사용한다. 이 브랜치는 언젠가 안정 상태 가 되겠지만, 항상 안정 상태를 유지해야 하는 것이 아니다. 테스트를 거쳐서 안정적이라고 판단되면 master 브랜치에 Merge 한다. 토픽 브랜치(앞서 살펴 본 iss53 브랜치 같은 짧은 호흡 브랜치)에도 적용할 수 있는데, 해당 토픽을 처리하고 테스트해서 버그도 없고 안정적이면 그때 Merge 한다. 사실 우리가 얘기하는 것은 커밋을 가리키는 포인터에 대한 얘기다. 개발 브랜치는 공격적으로 히스토리를 만들어 나아가고 안정 브랜치는 이미 만든 히스토리를 뒤따르며 나아간다.

 

안정적인 브랜치일수 록 커밋 히스토리가 뒤쳐진다

 

 

각 브랜치를 하나의 “실험실”로 생각하라

코드를 여러 단계로 나누어 안정성을 높여가며 운영할 수 있다. 프로젝트 규모가 크면 proposed 혹은 pu(proposed updates)라는 이름의 브랜치를 만들 고 next나 master 브랜치에 아직 Merge 할 준비가 되지 않은 것을 일단 Merge 시킨다. 중요한 개념은 브랜치를 이용해 여러 단계에 걸쳐서 안정화해 나아가 면서 충분히 안정화가 됐을 때 안정 브랜치로 Merge 한다는 점이다. 다시 말해 서 Long-Running의 브랜치가 여러 개일 필요는 없지만 정말 유용하다는 점이 다. 특히 규모가 크고 복잡한 프로젝트일수록 그 유용성이 반짝반짝 빛난다.

 

토픽 브랜치

 

토픽 브랜치는 프로젝트 크기에 상관없이 유용하다. 토픽 브랜치는 어떤 한 가지 주제나 작업을 위해 만든 짧은 호흡의 브랜치다. 다른 버전 관리 시스 템에서는 이런 브랜치를 본 적이 없을 것이다. Git이 아닌 다른 버전 관리 도구 에서는 브랜치를 하나 만드는 데 큰 비용이 든다. Git에서는 매우 일상적으로 브랜치를 만들고 Merge 하고 삭제한다.

 

앞서 사용한 iss53이나 hotfix 브랜치가 토픽 브랜치다. 우리는 브랜치를 새로 만들고 어느 정도 커밋하고 나서 다시 master 브랜치에 Merge 하고 브랜 치 삭제도 해 보았다. 보통 주제별로 브랜치를 만들고 각각은 독립돼 있기 때 문에 매우 쉽게 컨텍스트 사이를 옮겨 다닐 수 있다. 묶음별로 나눠서 일하면 내용별로 검토하기에도, 테스트하기에도 더 편하다. 각 작업을 하루든 한 달 이든 유지하다가 master 브랜치에 Merge 할 시점이 되면 순서에 관계없이 그 때 Merge 하면 된다.

 

master 브랜치를 checkout 한 상태에서 어떤 작업을 한다고 해보자. 한 이 슈를 처리하기 위해서 iss91 브랜치를 만들고 해당 작업을 한다. 같은 이슈를 다른 방법으로 해결해보고 싶을 때도 있다. iss91v2 브랜치를 만들고 다른 방 법을 시도해 본다. 확신할 수 없는 아이디어를 적용해보기 위해 다시 master 브랜치로 되돌아가서 dumbidea 브랜치를 하나 더 만든다. 지금까지 말했던 커밋 히스토리는 아래 그림 같다.

 

토픽 브랜치가 많다

이슈를 처리했던 방법 중 두 번째 방법인 iss91v2 브랜치가 괜찮아서 적용 하기로 결정했다. 그리고 아이디어를 확신할 수 없었던 dumbidea 브랜치를 같이 일하는 다른 개발자에게 보여줬더니 썩 괜찮다는 반응을 얻었다. iss91 브랜치는 (C5, C6 커밋도 함께) 버리고 다른 두 브랜치를 Merge 하면 아래 그림 과 같이 된다.

 

dumbidea와 iss91v2 브랜치를 Merge 하고 난 후의 모습

지금까지 한 작업은 전부 로컬에서만 처리한다는 것을 꼭 기억하자. 로컬 저장소에서만 브랜치를 만들고 Merge 했으며 서버와 통신을 주고받는 일은 없었다.

 

리모트 브랜치

리모트 Refs는 리모트 저장소에 있는 포인터인 레퍼런스다. 리모트 저장소 에 있는 브랜치, 태그, 등등을 의미한다. git ls-remote (remote) 명령으로 모든 리모트 Refs를 조회할 수 있다. git remote show (remote) 명령은 모 든 리모트 브랜치와 그 정보를 보여준다. 리모트 Refs가 있지만 보통은 리모트 트래킹 브랜치를 사용한다.

 

리모트 트래킹 브랜치는 리모트 브랜치를 추적하는 브랜치다. 이 브랜치는 로컬에 있지만 욺직일 수 없다. 리모트 서버에 연결할 때마다 리모트 브랜치 에 따라서 자동으로 욺직일 뿐이다. 리모트 트래킹 브랜치는 일종의 북마크라 고 할 수 있다. 리모트 저장소에 마지막으로 연결했던 순간에 브랜치가 무슨 커밋을 가리키고 있었는지를 나타낸다

 

리모트 브랜치의 이름은 (remote)/(branch) 형식으로 되어 있다. 예를 들어 리모트 저장소 origin의 master 브랜치를 보고 싶다면 origin/master 라는 이름으로 브랜치를 확인하면 된다. 다른 팀원과 함께 어떤 이슈를 구현 할 때 그 팀원이 iss53 브랜치를 서버로 Push 했고 당신도 로컬에 iss53 브랜 치가 있다고 가정하자. 이때 서버의 iss53 브랜치가 가리키는 커밋은 로컬에 서 origin/iss53이 가리키는 커밋이다. 다소 헷갈릴 수 있으니 예제를 좀 더 살펴보자. git.ourcompany.com이라 는 Git 서버가 있고 이 서버의 저장소를 하나 Clone 하면 Git은 자동으로 origin이라는 이름을 붙인다. origin으로부터 저장소 데이터를 모두 내려받고 master 브랜치를 가리키는 포인터를 만든다. 이 포인터는 origin/master라 고 부르고 멋대로 조종할 수 없다. 그리고 Git은 로컬의 master 브랜치가 origin/master를 가리키게 한다. 이제 이 master 브랜치에서 작업을 시작할 수 있다.

 

“ORIGIN”의 의미 브랜치 이름으로 많이 사용하는 “master”라는 이름이 괜히 특별한 의미를 가지는 게 아닌 것처럼 “origin”도 특별한 의미가 있는 것은 아니다. git init 명령이 자동 으로 만들기 때문에 사용하는 이름인 “master”와 마찬가지로 “origin”도 git clone 명령이 자동으로 만들어주는 리모트 이름이다. git clone -o booyah 라고 옵션을 주고 명령을 실행하면 booyah/master 라고 사용자가 정한 대로 리모트 이름 을 생성해준다.

Clone 이후 서버와 로 컬의 master 브랜치

로컬 저장소에서 어떤 작업을 하고 있는데 동시에 다른 팀원이 git.ourcompany.com 서버에 Push 하고 master 브랜치를 업데이트한다. 그러면 이제 팀원 간의 히스토리는 서로 달라진다. 서버 저장소로부터 어떤 데이터도 주고 받지 않아서 origin/master 포인터는 그대로다

 

로컬과 서버의 커밋 히스토리는 독립적임

리모트 서버로부터 저장소 정보를 동기화하려면 git fetch origin 명령 을 사용한다. 명령을 실행하면 우선 “origin” 서버의 주소 정보(이 예에서는 git.ourcompany.com)를 찾아서, 현재 로컬의 저장소가 갖고 있지 않은 새로 운 정보가 있으면 모두 내려받고, 받은 데이터를 로컬 저장소에 업데이트하고 나서, origin/master 포인터의 위치를 최신 커밋으로 이동시킨다.

 

git fetch 명령은 리 모트 브랜치 정보를 업데이트

리모트 저장소를 여러 개 운영하는 상황을 이해할 수 있도록 개발용으로 사용할 Git 저장소를 팀 내부에 하나 추가해 보자.

 

git remote add 명령으로 현재 작업 중인 프로젝트에 팀의 저장소를 추가한다. 이름을 teamone으로 짓고 긴 서버 주소 대신 사용한다.

 

서버를 리모트 저장소 로 추가

서버를 추가하고 나면 git fetch teamone 명령으로 teamone 서버의 데 이터를 내려받는다. 명령을 실행해도 teamone 서버의 데이터는 모두 origin 서버에도 있는 것들이라서 아무것도 내려받지 않는다. 하지만, 이 명령은 리 모트 트래킹 브랜치 teamone/master가 teamone 서버의 master 브랜치가 가 리키는 커밋을 가리키게 한다.

 

teamone/master의 리모트 트래킹 브랜치

Push 하기

 

로컬의 브랜치를 서버로 전송하려면 쓰기 권한이 있는 리모트 저장소에 Push 해야 한다. 로컬 저장소의 브랜치는 자동으로 리모트 저장소로 전송되지 않는다. 명시적으로 브랜치를 Push 해야 정보가 전송된다. 따라서 리모트 저 장소에 전송하지 않고 로컬 브랜치에만 두는 비공개 브랜치를 만들 수 있다. 또 다른 사람과 협업하기 위해 토픽 브랜치만 전송할 수도 있다. serverfix라는 브랜치를 다른 사람과 공유할 때에도 브랜치를 처음 Push 하는 것과 같은 방법으로 Push 한다. 아래와 같이 git push (remote) (branch) 명령을 사용한다.

 

102p까지봄