공개 소규모 팀
공개 팀을 운영 할 때에는 모든 개발자가 프로젝트 공유 저장소에 직접적으로 쓰기 권한을 가지지 않는다. 그래서 프로젝트 관리자는 몇가지 일을 더 해줘야 한다.
Fork를 지원하는 Git호스팅에서 Fork를 통해 프로젝트에 기여하는 법을 예제를 통해 살펴본다.
- repo.or.cz나 Github 같은 Git 호스팅 사이트느 Fork 기능을 지원하며 프로젝트 관리자는 보통 Fork하는 것으로 프로젝트를 운영한다.
- 다른 방식으로 이메일과 Patch를 사용하는 방식도 있다.
우선 처음 할 일은 메인 저장소를 Clone 하는 것이다. 그러고 나서 토픽 브랜치를 만들고 일정 부분 기여한다.
$ git clone <url>
$ cd project
$ git checkout -b featureA
... work ...
$ git commit
... work ...
$ git commit
일단 프로젝트의 웹사이트로 가서 'Fork' 버튼을 누르면 원래 프로젝트 저장소에서 갈라져 나온, 쓰기 권한이 있는 저장소가 하나 만들어진다. 그러면 로컬에서 수정한 커밋을 외부에 있는 그 저장소에 Push할 수 있다.
그 저장소를 로컬 저장소의 리모트 저장소로 등록한다.
$ git remote add myfork <url>
이제 등록한 리모트 저장소에 Push한다.
- 작업하던 것을 로컬 저장소의 master 브랜치에 Merge한 후 Push하는 것보다 리모트 브랜치에 Push를 하는 방식이 훨씬 간단하다.
- 이렇게 하는 이유는 관리자가 토픽브랜치를 프로젝트에 포함시키고 싶지 않을 때 토픽 브랜치를 Merge하기 이전 상태로 master 브랜치를 되돌릴 필요가 없기 때문이다.
- 관리자가 토픽 브랜치를 Merge하든 Rebase하든 Cherry-pick하든지 간에 결국 다시 관리자의 저장소를 Pull할 때에는 토픽 브랜치의 내용이 들어있을 것이다.
$ git push -u myfork featureA
Fork한 저장소에 Push하고 나면 프로젝트 관리자에게 이 내용을 알려야한다. 이것을 'Pull Reqeust' 라고 한다.
- git 호스팅 사이트에서 관리자에게 보낼 메시지를 생성하거나 git request-pull 명령으로 이메일을 수동으로 만들 수 있다.
- GitHub의 "pull request" 버튼은 자동으로 메시지를 만들어준다.
request-pull 명령은 아규먼트 두 개를 입력받는다.
- 작업한 토픽 브랜치의 Base 브랜치
- 토픽 브랜치가 위치한 저장소 URL(위에서 등록한 리모트 저장소 이름)
이 명령은 토픽 브랜치 수정사항의 요약한 내용을 결과로 보여준다.
예를 들어 Jessica가 John에게 Pull 요청을 보내는 상황을 살펴보자. Jessica는 토픽 브랜치를 두번 커밋을 하고 Fork한 저장소에 Push했다. 그리고 다음과 같이 실행한다.
$ git request-pull origin/master myfork
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
Jessica Smith (1):
added a new function
are available in the git repository at:
git://githost/simplegit.git featureA
Jessica Smith (2):
add limit to log function
change log output to 30 from 25
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
관리자에게 이 내용을 보낸다. 이 내용에는 토픽 브랜치가 어느 시점에 갈라져 나온 것인지, 어떤 커밋이 있는지, Pull 하려면 어떤 저장소에 접근해야 하는지에 대한 내용이 들어있다.
프로젝트 관리자가 아니라고 해도 보통 origin/master를 추적하는 master 브랜치는 가지고 있다. 그래도 토픽 브랜치를 만들고 일을 하면 관리자가 수정 내용을 거부할 때 쉽게 버릴 수 있다. 토픽별로 브랜치를 분리해서 일을 하면 그 동안 주 저장소의 master 브랜치가 수정됐기 때문에 깨끗한 커밋을 남기지 못할 수도 있지만. Rebase로 깨끗하게 Merge 할 수 있다. 그리고 토픽 브랜치를 새로 만들때 앞서 Push한 토픽 브랜치에서 시작하지 말고 주 저장소의 master 브랜치로 부터 만들어야 한다.
$ git checkout -b featureB origin/master
... work ...
$ git commit
$ git push myfork featureB
$ git request-pull origin/master myfork
... email generated request pull to maintainer ...
$ git fetch origin
각 토픽은 일종의 실험실이라고 할 수 있다. 각 토픽은 서로 방해하지 않고 독립적으로 수정하고 Rebase할 수 있다.
프로젝트 관리자가 사람들의 수정사항을 Merge하고 나서 Jessica의 브랜치를 Merge하려고 할 때 충돌이 날 수도 있다. 그러면 Jessica가 자신의 브랜치를 origin/master에 Rebase해서 충돌을 해결하고 다시 Pull Reqeust를 보낸다.
$ git checkout featureA
$ git rebase origin/master
$ git push -f myfork featureA
위 명령들을 실행하고 나면 다음과 같아진다.
브랜치를 Rebase해 버렸기 때문에 Push할 때 -f 옵션을 주고 강제로 기존 서버에 있던 브랜치의 내용을 덮어써야 한다. 아니면 새로운 브랜치를 (예 featureAv2) 서버에 Push해도 된다.
또 다른 시나리오를 하나 더 살펴보자.
- 프로젝트 관리자는 featureB 브랜치의 내용은 좋지만, 상세 구현은 다르게 하고 싶다.
- 관리자는 featureB 담당자에게 상세 구현을 다르게 해달라고 요청한다.
- featureB 담당자는 하는 김에 featureB 브랜치를 프로젝트의 최신 master 브랜치 기반으로 옮긴다.
- 먼저 origin/master 브랜치에서 featureBv2 브랜치를 하나 만들고, featureB의 커밋들을 Squash해서 Merge하고, 만약 충돌이 나면 해결하고, 상세 구현을 수정하고, 새 브랜치를 Push한다.
- --squash 옵션 : 현재 브랜치에 Merge할 때 해당 브랜치의 커밋을 모두 하느의 커밋으로 합쳐서 Merge 한다.
- --no-commit 옵션 : Git은 Merge하고 나서 자동으로 커밋하지 않는다. 다른 브랜치의 수정사항을 통째로 새로운 브랜치에 Merge하고 나서 좀 더 수정하고 커밋 하나를 새로 만든다.
$ git checkout -b featureBv2 origin/master
$ git merge --no-commit --squash featureB
... change implementation ...
$ git commit
$ git push myfork featureBv2
수정을 마치면 관리자에게 featureBv2 브랜치를 확인해 보라고 메시지를 보낸다.
대규모 공개 프로젝트
대규모 프로젝트는 보통 수정사항이나 Patch를 수용하는 자신만의 규칙을 마련해 놓고있다. 프로젝트마다 규칙은 서로 다를 수 있으므로 각 프로젝트의 규칙을 미리 알아둘 필요가 있다. 대규모 프로젝트는 대부분 메일링리스트를 통해서 Patch를 받아들인다. 예제를 통해 살펴보겠다.
토픽 브랜치를 만들어 수정하는 작업은 앞서 살펴본 바와 거의 비슷하지만 Patch를 제출하는 방식이 다르다. 프로젝트를 Fork 하여 Push하는 것이 아니라 커밋 내용을 메일로 만들어 개발자 메일링리스트에 제출한다.
$ git checkout -b topicA
... work ...
$ git commit
... work ...
$ git commit
커밋을 두 번 하고 메일링리스트에 보내 보자. git format-patch 명령으로 메일링리스트에 보낼 mobx 형식의 파일을 생성한다. 각 커밋은 하나씩 메일 메시지로 생성되는데 커밋 메시지의 첫 번째 줄이 제목이 되고 Merge 메시지 내용과 Patch 자체가 메일 메시지의 본문이 된다. 이 방식은 수신한 이메일에 들어있는 Patch를 바로 적용할 수 있어서 좋다. 메일 속에는 커밋의 모든 내용이 포함된다. 메일에 포함된 Patch를 적용하는 것은 다음 절에서 살펴본다.
format-patch 명령을 실행하면 생성한 파일 이름을 보여준다. -M 옵션은 이름이 변경된 파일이 있는지 살펴보라는 옵션이다.
$ git format-patch -M origin/master
0001-add-limit-to-log-function.patch
0002-changed-log-output-to-30-from-25.patch
각 파일의 내용은 다음과 같다.
$ cat 0001-add-limit-to-log-function.patch
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] add limit to log function
Limit log functionality to the first 20
---
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
end
def log(treeish = 'master')
- command("git log #{treeish}")
+ command("git log -n 20 #{treeish}")
end
def ls_tree(treeish = 'master')
--
1.6.2.rc1.20.g8c5b.dirty
메일링리스트에 메일을 보내기 전에 각 Patch 메일 파일의 내용을 손으로 고칠 수 있다. --줄과 Patch가 시작되는 줄(lib/simplegit.rb로 시작하는 줄) 사이에 내용을 추가하면 개발자는 읽을 수 있지만, 나중에 Patch에 적용되지는 않는다.
특정 메일 프로그램을 사용하거나 이베일을 보내는 명령어로 메일링스트에 보낼 수 있다. 붙여넣기로 위의 내용이 그대로 들어가지 않는 메일 프로그램도 있다. 사용자 편의를 위해 공백이나 줄 바꿈 문자 등을 넣어주는 메일 프로그램은 원본 그대로 들어가지 않는다.
다행히 Git에는 Patch 메일을 그대로 보낼 수 있는 도구가 있다. IMAP 프로토콜로 보낸다. 필자가 사용하는 방법으로 Gmail을 사용하여 Patch 메일을 전송하는 방법을 살펴보자. 참고로 Git 프로젝트의 Documentation/SubmittingPatches 문서의 마지막 부분에서 다양한 메일 프로그램으로 메일을 보내는 방법을 설명하고 있다.
메일을 보내려면 먼저 ~/.gitconfig 파일에서 이메일 부분 설정한다. git config 명령으로 추가할 수도 있고 직접 파일을 열얼서 추가할 수도 있다. 아무튼 다음과 같이 설정을 한다.
[imap]
folder = "[Gmail]/Drafts"
host = imaps://imap.gmail.com
user = user@gmail.com
pass = p4ssw0rd
port = 993
sslverify = false
IMAP 서버가 SSL을 사용하지 않으면 마지만 두 줄은 필요없고 host에서 imaps://대신 imap://로 한다. 이렇게 설정하면 git send-email 명령으로 메일을 전송할 수 있다.
$ git send-email *.patch
0001-added-limit-to-log-function.patch
0002-changed-log-output-to-30-from-25.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? y
Git으로 메일을 보내면 다음과 같은 로그 메시지가 출력된다.
(mbox) Adding cc: Jessica Smith <jessica@example.com> from
\line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] added limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>
Result: OK
이후 Gmail의 Draft 폴더로 가서 To 부분을 메일링리스트의 주소로 변경하고 CC부분에 해달 메일을 참고해야 하는 관리자나 개발자의 메일 주소를 적고 실제로 전송한다.
요약
이번 절에서는 다양한 Workflow에 따라 Git을 어떻게 사용하는지 살펴보고 그에 필요한 도구들을 설명했다. 다음 절에서는 동전의 뒷면인 프로젝트를 운영하는 방법에 대하여 살펴본다. 즉 친절한 Dictator나 Intergration-Manager가 되어 보는 것이다.
'책 > 프로 Git' 카테고리의 다른 글
Git 도구-1 - 리비전 조회하기 (0) | 2020.07.29 |
---|---|
분산 환경에서의 Git-5 - 프로젝트 운영하기 (0) | 2020.07.29 |
분산 환경에서의 Git-2 - 프로젝트에 기여하기 - 비공개 소규모 팀 (0) | 2020.07.28 |
분산 환경에서의 Git-3 - 프로젝트에 기여하기 - 비공개 대규모 팀 (0) | 2020.07.28 |
분산 환경에서의 Git-1 - 분산 환경에서의 Workflow (0) | 2020.07.28 |