Git --everything-is-local

5.1 분산 환경에서의 Git - 분산 환경에서의 Workflow

분산 환경에서의 Workflow

중앙집중형 버전 관리 시스템과는 달리 Git은 분산형이다. Git의 구조가 훨씬 더 유연하기 때문에 여러 개발자가 함께 작업하는 방식을 더 다양하게 구성할 수 있다. 중앙집중형 버전 관리 시스템에서 각 개발자는 중앙 저장소를 중심으로 하는 하나의 노드일 뿐이다. 하지만, Git에서는 각 개발자의 저장소가 하나의 노드이기도 하고 중앙 저장소 같은 역할도 할 수 있다. 즉, 모든 개발자는 다른 개발자의 저장소에 일한 내용을 전송하거나, 다른 개발자들이 참여할 수 있도록 자신이 운영하는 저장소 위치를 공개할 수도 있다. 이런 특징은 프로젝트나 팀이 코드를 운영할 때 다양한 Workflow을 만들 수 있도록 해준다. 이런 유연성을 살려 저장소를 운영하는 몇 가지 방식을 소개한다. 각 방식의 장단점을 살펴보고 그 방식 중 하나를 고르거나 여러 가지를 적절히 섞어 쓰면 된다.

중앙집중식 Workflow

중앙집중식 시스템에서는 보통 중앙집중식 협업 모델이라는 한 가지 방식밖에 없다. 중앙 저장소는 딱 하나 있고 변경 사항은 모두 이 중앙 저장소에 집중된다. 개발자는 이 중앙 저장소를 중심으로 작업한다(그림 5-1).


그림 5-1. 중앙집중식 Workflow

중앙집중식에서 개발자 두 명이 중앙저장소를 Clone하고 각자 수정하는 상황을 생각해보자. 한 개발자가 자신이 한 일을 커밋하고 나서 아무 문제 없이 서버에 Push한다. 그러면 다른 개발자는 자신의 일을 커밋하고 Push하기 전에 첫 번째 개발자가 한 일을 먼저 Merge해야 한다. Merge를 해야 첫 번째 개발자가 작업한 내용을 덮어쓰지 않는다. 이런 개념은 Subversion과 같은 중앙집중식 버전 관리 시스템에서 사용하는 방식이고 Git에서도 당연히 이런 Workflow를 사용할 수 있다.

팀이 작거나 이미 중앙집중식에 적응한 상황이라면 이 Workflow에 따라 Git을 도입하여 사용할 수 있다. 중앙 저장소를 하나 만들고 개발자 모두에게 Push 권한을 부여한다. 모두에게 Push 권한을 부여해도 Git은 한 개발자가 다른 개발자의 작업 내용을 덮어쓰도록 허용하지 않는다. 한 개발자가 Clone하고 나서 수정하는 사이에 이미 다른 개발자가 중앙 저장소에 무언가 Push했다면 이 개발자는 Push할 수 없다. Git은 개발자에게 지금 Push하려는 커밋으로 Fast-forward할 수 없으니 Fetch하고 Merge해야 서버로 Push할 수 있다고 알려준다. 이런 개념은 개발자에게 익숙해서 거부감 없이 도입할 수 있다.

Integration-Manager Workflow

Git을 사용하면 리모트 저장소를 여러 개 운영할 수 있다. 다른 개발자는 읽기만 가능하고 자신은 쓰기도 가능한 공개 저장소를 만드는 Workflow도 가능하다. 이 Worlflow에는 보통 프로젝트를 대표하는 하나의 공식 저장소가 있다. 기여자는 우선 공식 저장소를 하나 Clone하고 수정하고 나서 자신의 저장소에 Push한다. 그다음에 프로젝트 Integration-Manager에게 새 저장소에서 Pull하라고 요청한다. 그러면 그 Integration-Manager는 기여자의 저장소를 리모트 저장소로 등록하고, 로컬에서 기여물을 테스트하고, 프로젝트 메인 브랜치에 Merge하고, 그 내용을 다시 프로젝트 메인 저장소에 Push한다. 이런 과정은 아래와 같다(그림 5-2).

  1. 프로젝트 Integration-Manager는 프로젝트 메인 저장소에 Push를 한다.
  2. 프로젝트 기여자는 메인 저장소를 Clone하고 수정한다.
  3. 기여자는 자신의 저장소에 Push하고 Integration-Manager가 접근할 수 있도록 공개해 놓는다.
  4. 기여자는 Integration-Manager에게 변경사항을 적용해 줄 것을 E-mail 같은 것으로 요청한다.
  5. Integration-Manager는 기여자의 저장소를 리모트 저장소로 등록하고 수정사항을 Merge하여 테스트한다.
  6. Integration-Manager는 Merge한 사항을 메인 저장소에 Push한다.


그림 5-2. Integration-Manager Workflow

이 방식은 GitHub 같은 사이트에서 주로 사용하는 방식이다. GitHub는 프로젝트를 Fork하고 수정사항을 반영하여 다시 모두에게 공개하기 좋은 구조로 되어 있다. 이 방식의 장점은 기여자와 Integration-Manager가 각자의 사정에 맞춰 프로젝트를 유지할 수 있다는 점이다. 기여자는 자신의 저장소와 브랜치에서 수정 작업을 계속해 나갈 수 있고 수정사항이 프로젝트에 반영되도록 기다릴 필요가 없다. 관리자는 여유를 가지고 기여자가 Push해 놓은 커밋을 적절한 시점에 Merge한다.

Dictator and Lieutenants Workflow

이 방식은 저장소를 여러개 운영하는 방식을 변형한 구조이다. 보통 수백 명의 개발자가 참여하는 아주 큰 프로젝트를 운영할 때 이 방식을 사용한다. 리눅스 커널 프로젝트가 대표적이다. 여러 명의 Integration-Manager가 저장소에서 자신이 맡은 부분만을 담당하는데 이들을 Lieutenants라고 부른다. 모든 Lieutenant는 최종 관리자 아래에 있으며 이 최종 관리자를 Dictator라고 부른다(그림 5-3).

  1. 개발자는 코드를 수정하고 master 브랜치를 기준으로 자신의 토픽 브랜치를 Rebase한다. 여기서 master 브랜치란 Dictator의 브랜치를 말한다.
  2. Lieutenant들은 개발자들의 수정사항을 자신이 관리하는 master 브랜치에 Merge한다.
  3. Dictator는 Lieutenant의 master 브랜치를 자신의 master 브랜치로 Merge한다.
  4. Dictator는 Merge한 자신의 master 브랜치를 Push하여 다른 모든 개발자가 Rebase할 수 있는 기준으로 만든다.


그림 5-3. Benevolent dictator Workflow

이 방식이 일반적이지 않지만 깊은 계층 구조를 가지는 환경이나 규모가 큰 프로젝트에서는 매우 쓸모 있다. 프로젝트 리더가 모든 코드를 통합하기 전에 코드를 부분부분 통합하도록 여러 명의 Lieutenant에게 위임한다.

이 세 가지 Workflow가 Git 같은 분산 버전 관리 시스템에서 주로 사용하는 것들이다. 사실 이런 Workflow뿐만 아니라 다양한 변종 Workflow가 실재로 사용된다. 어떤 방식을 선택하고 혹은 조합해야 하는 지 살짝 감이 잡힐 것이다. 이 장에서는 몇 가지 구체적 사례를 들고 우리가 다양한 환경에서 각 역할을 어떻게 수행하는지 살펴본다.