git과 Perl 저장소

git과 Perl 저장소 (perlgit)

이 문서는 Perl 개발에 git을 쓰는 방법을 상세히 다뤄요. 빠른 패치 작업만 관심 있다면 perlhack을 먼저 보세요. 이 문서는 Perl에 정기적으로 기여하는 사람, 특히 git 저장소에 쓰기 권한이 있는 사람을 대상으로 해요.

Perl의 전체 소스 코드는 github.com의 Git 저장소에 중앙 집중식으로 보관돼요.

출처: perlgit - Detailed information about git and the Perl repository

본문

DESCRIPTION

이 문서는 Perl 개발에 git을 쓰는 자세한 내용을 다뤄요. 빠른 패치만 하고 싶다면 perlhack을 먼저 보세요. 이 문서는 git 저장소에 쓰기 권한이 있는 사람을 포함해 Perl에 정기적으로 기여하는 사람을 대상으로 해요.

CLONING THE REPOSITORY

Perl의 모든 소스 코드는 github.com의 Git 저장소에 중앙 집중식으로 보관돼요.

다음을 실행해 저장소를 읽기 전용으로 클론할 수 있어요:

% git clone [email protected]:Perl/perl5.git perl

방화벽 때문에 그게 안 되면 http로도 클론할 수 있어요:

% git clone https://github.com/Perl/perl5.git perl

WORKING WITH THE REPOSITORY

저장소 디렉터리로 들어가면 그것을 조사할 수 있어요. 클론 후 저장소에는 단일 로컬 브랜치가 있고, 별표가 나타내듯 그것이 곧 현재 브랜치예요.

% git branch
* blead

branch에 -a 스위치를 쓰면 저장소의 원격 추적 브랜치도 보여줘요:

% git branch -a
* blead
  origin/HEAD
  origin/blead
...

"origin"으로 시작하는 브랜치는 클론한 "git remote"(이름이 "origin")에 대응해요. 원격의 각 브랜치는 이 브랜치들로 정확히 추적돼요. 이 원격 추적 브랜치에서는 절대 작업하면 안 돼요. 로컬 브랜치에서만 작업하세요. 로컬 브랜치는 (pull 시) 지정된 원격 추적 브랜치에서 자동 병합되도록 설정할 수 있어요. 기본 브랜치 blead가 그런 경우인데, 원격 추적 브랜치 origin/blead에서 병합되도록 설정돼 있을 거예요.

최근 커밋을 볼 수 있어요:

% git log

그리고 저장소에서 새 변경을 끌어와 로컬 저장소를 갱신할 수 있어요(먼저 깨끗해야 해요):

% git pull

pull 직후 blead 브랜치에 있다고 가정하면 이 명령은 대략 다음과 동등해요:

% git fetch
% git merge origin/blead

사실 작업 디렉터리를 건드리지 않고 로컬 저장소만 갱신하려면 이렇게 해요:

% git fetch

모든 정의된 리모트의 원격 추적 브랜치를 동시에 갱신하려면 이렇게 해요:

% git remote update

이 마지막 두 명령 중 어느 것도 작업 디렉터리를 갱신하지 않지만, 둘 다 저장소의 원격 추적 브랜치는 갱신해요.

원격 브랜치의 로컬 브랜치를 만들려면:

% git checkout -b maint-5.10 origin/maint-5.10

blead로 돌아가려면:

% git checkout blead

상태 확인하기 (Finding out your status)

가장 흔히 쓰는 git 명령은 아마 이거예요:

% git status

이 명령은 저장소의 현재 상태 설명을 출력하는데, 수정된 파일과 무시되지 않은 추적 안 된 파일을 포함하고, 다음 커밋을 위해 어떤 파일이 staged 됐는지 같은 것과 보통 어떤 변화를 일으키는 방법에 대한 유용한 정보를 보여줘요. 예를 들어:

% git status
On branch blead
Your branch is ahead of 'origin/blead' by 1 commit.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

      modified:   pod/perlgit.pod

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working
                                                             directory)

      modified:   pod/perlgit.pod

Untracked files:
  (use "git add <file>..." to include in what will be committed)

      deliberate.untracked

이것은 커밋을 위해 이 문서의 변경이 staged 됐고, 작업 디렉터리에는 아직 staged 되지 않은 추가 변경이 있다는 걸 보여줘요. 또한 작업 디렉터리에 추적 안 된 파일이 있고, 이 모든 걸 바꾸는 방법을 보여주기도 해요. 그리고 작업 브랜치 blead에 아직 origin 리모트로 push되지 않은 커밋이 하나 있다는 것도 보여줘요. NOTE: 이 출력은 git commit에 메시지를 주지 않으면 템플릿으로 보게 되는 것이기도 해요.

패치 워크플로우 (Patch workflow)

먼저 Perl 코어 해킹에 대한 자세한 내용은 perlhack을 읽어 주세요. 그 문서는 좋은 패치를 만드는 방법의 많은 세부사항을 다뤄요.

이미 Perl 저장소가 있다면 blead 브랜치에 있고 저장소가 최신인지 확인해야 해요:

% git checkout blead
% git pull

치명적 버그 수정을 제외한 모든 변경의 새 개발이 일어나는 곳이 최신 blead이므로, 최신 blead에 대해 패치하는 게 바람직해요. 치명적 버그 수정 패치는 관련 maint 브랜치에 대해 만드거나, 수정이 적용돼야 할 모든 브랜치를 표시한 메모와 함께 제출해야 해요.

이제 모든 게 최신이니, 이 변경을 위한 임시 새 브랜치를 만들고 그 안으로 전환해야 해요:

% git checkout -b orange

이것은 다음의 짧은 형태예요:

% git branch orange
% git checkout orange

토픽 브랜치를 만들면 유지보수자가 더 선형적인 히스토리를 위해 blead master로 rebase하거나 병합하기 쉬워져요. 토픽 브랜치에서 작업하지 않으면 유지보수자가 적용 전에 변경을 blead에 수동으로 cherry pick해야 해요.

그러면 perl5-porters에서 꾸중을 들을 테니 그러지 마세요. 멋지게 행동하세요.

그다음 변경을 만들면 돼요. 예를 들어 Leon Brocard가 이름을 Orange Brocard로 바꾸면, AUTHORS 파일에서 그의 이름을 바꿔야 할 거예요:

% perl -pi -e 's{Leon Brocard}{Orange Brocard}' AUTHORS

어떤 파일이 바뀌었는지 볼 수 있어요:

% git status
On branch orange
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

   modified:   AUTHORS

그리고 변경 내용을 볼 수 있어요:

% git diff
diff --git a/AUTHORS b/AUTHORS
index 293dd70..722c93e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -541,7 +541,7 @@    Lars Hecking              <[email protected]>
 Laszlo Molnar                  <[email protected]>
 Leif Huhn                      <[email protected]>
 Len Johnson                    <[email protected]>
-Leon Brocard                   <[email protected]>
+Orange Brocard                 <[email protected]>
 Les Peters                     <[email protected]>
 Lesley Binks                   <[email protected]>
 Lincoln D. Stein               <[email protected]>

이제 변경을 로컬에서 커밋해요:

% git commit -a -m 'Rename Leon Brocard to Orange Brocard'
Created commit 6196c1d: Rename Leon Brocard to Orange Brocard
 1 files changed, 1 insertions(+), 1 deletions(-)

-a 옵션은 변경한 git이 추적하는 모든 파일을 포함하는 데 써요. 이 시점에 작업한 파일의 일부만 커밋하고 싶다면 -a를 빼고 커밋 전에 git add *FILE ...* 명령을 쓰면 돼요. git add --interactive로 파일 전체 변경 대신 일부만 커밋할 수도 있어요.

-m 옵션은 커밋 메시지를 지정하는 데 써요. 생략하면 git이 텍스트 편집기를 열어 메시지를 대화형으로 작성하게 해요. 변경이 여기 예시보다 복잡할 때 유용하고, 편집기에 따라 커밋 메시지 첫 줄이 50자 법적 최대치를 넘지 않는지 아는 데도 좋아요. 좋은 커밋 메시지가 무엇인지에 대한 더 많은 정보는 "Commit message" in perlhack를 보세요.

커밋 메시지 작성을 끝내고 편집기를 나가면 git이 변경을 디스크에 쓰고 이렇게 말할 거예요:

Created commit daf8e63: explain git status and stuff about remotes
 1 files changed, 83 insertions(+), 3 deletions(-)

git status를 다시 실행하면 이렇게 보여야 해요:

% git status
On branch orange
Untracked files:
  (use "git add <file>..." to include in what will be committed)

      deliberate.untracked

nothing added to commit but untracked files present (use "git add" to
                                                                 track)

의심스러우면 다른 일 하기 전에 상태를 확인하고 주의 깊게 읽어 보세요. 많은 질문이 git status 출력에 직접 답돼 있어요.

마지막 커밋을 이렇게 검사할 수 있어요:

% git show HEAD

그리고 설명이나 패치 자체가 마음에 안 들면 파일을 한 번 더 편집해 고친 뒤 이렇게 하면 돼요:

% git commit -a --amend

이제 브랜치를 push할 GitHub fork를 만들고, 아직 안 했다면 리모트로 추가해요. GitHub 문서 https://help.github.com/en/articles/working-with-forks에 설명돼 있어요:

% git remote add fork [email protected]:MyUser/perl5.git

그리고 브랜치를 fork에 push해요:

% git push -u fork orange

이제 GitHub에서 새 브랜치에서 blead로 Pull Request(PR)를 제출해야 해요. 더 많은 정보는 https://help.github.com/en/articles/creating-a-pull-request-from-a-fork의 GitHub 문서를 보세요.

패치가 적용될 준비가 되지 않았지만 논의를 위한 것이라면 [email protected]에 패치 파일을 직접 보낼 수도 있어요.

모든 로컬 변경에 대한 패치 파일을 만들려면:

% git format-patch -M blead..
0001-Rename-Leon-Brocard-to-Orange-Brocard.patch

또는 많은 변경(예: 토픽 브랜치에서)이라면:

% git format-patch --stdout -M blead.. > topic-branch-changes.patch

임시 브랜치를 삭제하려면 이렇게 하면 돼요:

% git checkout blead
% git branch -d orange
error: The branch 'orange' is not an ancestor of your current HEAD.
If you are sure you want to delete it, run 'git branch -D orange'.
% git branch -D orange
Deleted branch orange.

파생 파일에 대한 메모 (A note on derived files)

배포판의 많은 파일이 파생적임을 알아두세요—패치하지 마세요. git이 그 변경을 보지 못할 것이고, 빌드 과정이 덮어쓸 테니까요. 대신 원본을 패치하세요. 대부분의 유틸리티(perldoc 같은)가 이 범주에 있어서, utils/perldoc 대신 utils/perldoc.PL을 패치해요. 마찬가지로 $src_root/ext 아래의 파일을 $install_root/lib에서 찾은 복사본으로부터 패치하지 마세요. 소스 배포판을 빌드하는 동안 복사됐을 수 있는 파일의 적절한 위치가 확실하지 않으면 MANIFEST를 참고하세요.

작업 디렉터리 정리 (Cleaning a working directory)

git clean 명령은 인자에 따라 make clean의 대체물로 쓸 수 있어요.

작업 디렉터리를 원래 상태로 리셋하려면 이렇게 해요:

% git clean -dxf

하지만 이건 추적 안 된 콘텐츠를 모두 삭제한다는 점을 주의하세요. 이렇게 하면:

% git clean -Xf

무시된 추적 안 된 파일(빌드·테스트 부산물 같은)을 모두 제거하지만, 수동으로 만든 파일은 그대로 두는 걸로 해요.

일부 미커밋 편집만 취소하고 싶다면 git checkout을 쓰고 되돌릴 파일 목록을 주거나, git checkout -f로 전부 되돌릴 수 있어요.

커밋 하나 또는 여러 개를 취소하려면 git reset을 쓸 수 있어요.

이분 탐색 (Bisecting)

git은 주어진 버그를 도입한 커밋이 어느 것인지 판별하는 내장 방법을 제공해요. git bisect는 히스토리의 이진 검색을 수행해 첫 실패 커밋을 찾아요. 빠르고 강력하며 유연하지만, 약간의 설정이 필요하고 과정을 자동화하려면 보조 셸 스크립트가 필요해요.

코어는 Porting/bisect.pl이라는 래퍼 프로그램을 제공해서, Perl 원라이너를 실행하는 것처럼 간단하게 bisect를 할 수 있게 최대한 단순화해요. 예를 들어 이것이 언제 오류가 됐는지 알고 싶다면:

perl -e 'my $x := 2'

그냥 이렇게 실행해요:

.../Porting/bisect.pl -e 'my $x := 2;'

Porting/bisect.pl을 쓰면 한 명령(그리고 다른 파일 없이)으로 쉽게 알아낼 수 있어요:

어떤 커밋이 이 예시 코드를 깨뜨렸는지?

어떤 커밋이 이 예시 코드가 동작하기 시작하게 했는지?

어떤 커밋이 이 정규 표현식에 일치하는 첫 파일을 추가했는지?

어떤 커밋이 이 정규 표현식에 일치하는 마지막 파일을 제거했는지?

보통 시작·끝 리비전으로 쓸 perl 버전을 알 필요 없이요. Porting/bisect.pl이 테스트 케이스가 통과하는 가장 이른 안정 버전을 찾으려 자동으로 검색하니까요. Configure와 빌드 타임 옵션 설정 방법을 포함한 전체 문서는 Porting/bisect.pl --help를 실행하세요.

Porting/bisect.pl이 제공하는 것보다 더 유연함이 필요하면 git bisect를 직접 실행해야 해요. perl 리비전 빌드·테스트를 자동화하는 데 git bisect run을 쓰는 게 가장 유용해요. 이를 위해 특정 리비전을 테스트하도록 git이 호출할 셸 스크립트가 필요해요. 예시 스크립트는 Porting/bisect-example.sh인데, bisect 과정이 실행하면서 상태를 깨끗한 체크아웃으로 리셋할 테니 저장소 밖으로 복사해야 해요. 아래 지침은 그것을 ~/run으로 복사한 뒤 적절히 편집했다고 가정해요.

먼저 bisect 모드로 들어가요:

% git bisect start

예를 들어 버그가 HEAD에는 있지만 5.10.0에는 없었다면, 이렇게 입력하면 git이 그것을 알게 돼요:

% git bisect bad
% git bisect good perl-5.10.0
Bisecting: 853 revisions left to test after this

이로써 HEADperl-5.10.0 사이의 중앙 커밋을 체크아웃하게 돼요. 그다음 이렇게 bisect 과정을 실행할 수 있어요:

% git bisect run ~/run

첫 나쁜 커밋이 격리되면 git bisect가 알려줘요:

ca4cfd28534303b82a216cfe83a1c80cbc3b9dc5 is first bad commit
commit ca4cfd28534303b82a216cfe83a1c80cbc3b9dc5
Author: Dave Mitchell <[email protected]>
Date:   Sat Feb 9 14:56:23 2008 +0000

    [perl #49472] Attributes + Unknown Error
    ...

bisect run success

git bisect loggit bisect visualize로 bisect 과정을 들여다볼 수 있어요. git bisect reset은 bisect 모드를 빠져나가게 해요.

good 상태는 첫 bad 상태의 조상이어야 한다는 점을 기억하세요. 어떤 버그를 해결한 커밋을 찾으려면 테스트 케이스를 반전시켜야 해요(즉 OK면 1로, 아니면 0으로 종료) 여전히 하한을 good으로, 상한을 bad로 표시해야 해요. 그러면 "first bad commit"은 "버그가 해결된 첫 커밋"으로 이해해야 해요.

git help bisect에 이진 검색을 조정하는 방법에 대한 훨씬 더 많은 정보가 있어요.

bisection 다음에는 bisection 과정이 식별한 커밋들에서 perl을 configure·build·test하고 싶을 수 있어요. 특히 오래된 perl에서 가끔 이 과정 중 make가 실패할 수 있어요. 그런 경우 더 오래된 커밋 지점에서 소스 코드를 패치할 수 있을지도 몰라요. 그렇게 하려면 "Building perl at older commits" in perlhack의 제안을 따라 주세요.

토픽 브랜치와 히스토리 다시 쓰기 (Topic branches and rewriting history)

개별 커미터는 여러분이름/설명적인_이름 지침 아래 토픽 브랜치를 만들어야 해요:

% branch="$yourname/$some_descriptive_name"
% git checkout -b $branch
... do local edits, commits etc ...
% git push origin -u $branch

1.7 이전의 오래된 git 버전에 갇혔다면 git push-u 스위치가 없어서, 마지막 단계를 다음 시퀀스로 대체해야 해요:

% git push origin $branch:refs/heads/$branch
% git config branch.$branch.remote origin
% git config branch.$branch.merge refs/heads/$branch

다른 사람의 토픽 브랜치를 바꾸고 싶다면, 어떤 변경도 하기 전에 그 창시자와 상의해야 해요.

때로 원저자가 브랜치의 히스토리를 편집한 걸 발견할 수 있어요. 여기엔 많은 좋은 이유가 있어요. 때로 저자는 단순히 브랜치를 더 새로운 소스 지점에 rebase하고 있을 수도 있어요. 때로 브랜치를 blead에 병합하기 전에 고치고 싶은 초기 커밋의 오류를 발견했을 수도 있어요.

현재 master 저장소는 non-fast-forward 병합을 금지하도록 설정돼 있어요. 즉 그 안의 브랜치는 rebase되어 한 단계로 push될 수 없어요.

push된 브랜치를 rebase하거나 그 히스토리를 수정할 수 있는 유일한 방법은 그것을 삭제하고 같은 이름의 새 브랜치로 push하는 거예요. 이렇게 하는 것을 신중히 생각하세요. 브랜치를 순차적으로 이름을 바꿔서 함께 작업하는 다른 사람들이 새 버전에 자신의 로컬 변경을 cherry-pick하기 쉽게 하는 게 더 나을 수도 있어요. (XXX: 설명 필요).

개인 토픽 브랜치를 rebase하고 싶다면, 기존 토픽 브랜치를 삭제하고 새 버전으로 push해야 해요. 브랜치를 rebase한 뒤 다음 공식(refspec에 대한 설명은 git push 문서 참고)으로 할 수 있어요:

# first rebase
% git checkout $user/$topic
% git fetch
% git rebase origin/blead

# then "delete-and-push"
% git push origin :$user/$topic
% git push origin $user/$topic

NOTE: 저장소 수준에서 "primary" 브랜치를 삭제하는 것은 금지돼 있어요. 즉 m!^(blead|maint|perl)!에 일치하는 어떤 브랜치든요. 그렇게 시도하면 git이 이런 오류를 내요:

% git push origin :blead
*** It is forbidden to delete blead/maint branches in this repository
error: hooks/update exited with error code 1
error: hook declined to update refs/heads/blead
To ssh://perl5.git.perl.org/perl
 ! [remote rejected] blead (hook declined)
 error: failed to push some refs to 'ssh://perl5.git.perl.org/perl'

정책으로 우리는 blead와 maint-* 브랜치의 히스토리를 편집하지 않습니다. 오타(또는 더 나쁜 것)가 blead나 maint-*에 대한 커밋에 들어가면 다른 커밋에서 고칠 거예요. 이 브랜치에 허용되는 갱신 유형은 히스토리가 모두 보존되는 "fast-forward"뿐이에요.

canonical perl.git 저장소의 주석이 달린 태그는 절대 삭제되거나 수정되지 않을 거예요. 로컬 태그를 perl.git에 push할지 여부를 정하기 전에 길고 깊게 생각하세요.(단순 태그 push는 허용되지 않아요.)

Graft (Grafts)

perl 히스토리에는 변환에서 잡히지 않은 실수가 하나 있어요: blead와 maint-5.10 사이에 실제로 병합이 일어나지 않았는데 병합이 기록됐어요. git의 특성상 이제 공개 저장소에서 이를 고치는 건 불가능해요. 로컬에서 이 잘못된 병합을 제거하려면 .git/info/grafts 파일에 다음 줄을 추가하면 돼요:

296f12bbbbaa06de9be9d09d3dcf8f4528898a49 434946e0cb7a32589ed92d18008aaa1d88515930

문제의 "병합" 근처에서 bisect를 하려면 특히 이 graft 줄이 있는 게 중요해요.

WRITE ACCESS TO THE GIT REPOSITORY

쓰기 권한이 생기면 origin 리모트의 URL을 수정해 push를 활성화해야 해요. git-config(1) 명령으로 .git/config를 편집해요:

% git config remote.origin.url [email protected]:Perl/perl5.git

사용자 이름과 이메일 주소도 설정할 수 있어요. 대부분 사람은 전역적으로 ~/.gitconfig에서 이렇게 한 번 해요:

% git config --global user.name "Ævar Arnfjörð Bjarmason"
% git config --global user.email [email protected]

하지만 그것을 perl에 대해서만 덮어쓰고 싶다면 perl에서 다음처럼 실행해요:

% git config user.email [email protected]

origin을 git 리모트로 유지하고 ssh 접근용 새 리모트를 추가하는 것도 가능해요:

% git remote add camel [email protected]:Perl/perl5.git

이렇게 하면 인증이 필요 없고 더 빠른 origin에서 pull해 로컬 저장소를 갱신하고, camel 리모트로 변경을 push할 수 있어요:

% git fetch camel
% git push camel

fetch 명령은 camel refs만 갱신해요. 객체 자체는 origin에서 pull할 때 이미 가져왔어야 하니까요.

GitHub pull request 작업 (Working with GitHub pull requests)

Pull request는 보통 Perl/perl.git 저장소 밖에서 시작하므로, 로컬에서 테스트하거나 작업하려면 Perl/perl5.git 저장소에서 빼온 일반 git fetch로는 가져오지 못해요.

하지만 GitHub는 pull request를 로컬 브랜치로 가져오는 메커니즘을 제공해요. 그것들은 GitHub 리모트에서 pull/ 아래에 있으므로, git fetch pull/*PRID*/head:*localname*을 써서 로컬 복사본을 만들 수 있어요. 예를 들어 pull request 9999를 로컬 브랜치 local-branch-name으로 가져오려면:

git fetch origin pull/9999/head:local-branch-name

그리고 나서:

git checkout local-branch-name

참고: 이 브랜치는 blead에 rebase돼 있지 않으므로 위의 checkout 대신 이걸 원할 수도 있어요:

git rebase origin/blead local-branch-name

이것은 local-branch-nameblead에 rebase하고 체크아웃해요.

대안으로 리모트가 모든 pull request를 원격 추적 브랜치로 가져오도록 설정할 수 있어요. 그러려면 .git/config에서 리모트를 편집해요. 예를 들어 GitHub 리모트가 origin이면 이렇게 있을 거예요:

[remote "origin"]
        url = [email protected]:/Perl/perl5.git
        fetch = +refs/heads/*:refs/remotes/origin/*

원격 pull request 브랜치를 원격 추적 브랜치로 매핑하는 줄을 추가해요:

[remote "origin"]
        url = [email protected]:/Perl/perl5.git
        fetch = +refs/heads/*:refs/remotes/origin/*
        fetch = +refs/pull/*/head:refs/remotes/origin/pull/*

그리고 평소처럼 fetch해요:

git fetch origin

이러면 닫힌 request를 포함해 모든 pull request에 대한 원격 추적 브랜치가 만들어져요.

그 원격 추적 브랜치들을 제거하려면 위에 추가한 줄을 제거하고 prune해요:

git fetch -p origin # or git remote prune origin

패치 수락하기 (Accepting a patch)

위 절을 사용해 생성된 패치 파일을 받았다면 패치를 시험해 봐야 해요.

먼저 이 변경을 위한 임시 새 브랜치를 만들고 그 안으로 전환해야 해요:

% git checkout -b experimental

git format-patch로 만든 패치는 git am으로 적용해요:

% git am 0001-Rename-Leon-Brocard-to-Orange-Brocard.patch
Applying Rename Leon Brocard to Orange Brocard

일부 UNIX 메일 시스템이 'From '을 포함한 텍스트 첨부를 망칠 수 있다는 점을 주의하세요. 이렇게 고칠 수 있어요:

% perl -pi -e's/^>From /From /' \
                       0001-Rename-Leon-Brocard-to-Orange-Brocard.patch

그냥 raw diff가 제공되면 이 2단계 과정을 쓰는 것도 가능해요:

% git apply bugfix.diff
% git commit -a -m "Some fixing" \
                           --author="That Guy <[email protected]>"

이제 변경을 살펴볼 수 있어요:

% git show HEAD
commit b1b3dab48344cff6de4087efca3dbd63548ab5e2
Author: Leon Brocard <[email protected]>
Date:   Fri Dec 19 17:02:59 2008 +0000

  Rename Leon Brocard to Orange Brocard

diff --git a/AUTHORS b/AUTHORS
index 293dd70..722c93e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -541,7 +541,7 @@ Lars Hecking                 <[email protected]>
 Laszlo Molnar                  <[email protected]>
 Leif Huhn                      <[email protected]>
 Len Johnson                    <[email protected]>
-Leon Brocard                   <[email protected]>
+Orange Brocard                 <[email protected]>
 Les Peters                     <[email protected]>
 Lesley Binks                   <[email protected]>
 Lincoln D. Stein               <[email protected]>

Perl 커미터이고 패치가 좋다고 생각하면, blead에 병합한 뒤 main 저장소로 push할 수 있어요:

% git checkout blead
% git merge experimental
% git push origin blead

임시 브랜치를 삭제하고 싶다면 이렇게 하면 돼요:

% git checkout blead
% git branch -d experimental
error: The branch 'experimental' is not an ancestor of your current
HEAD.  If you are sure you want to delete it, run 'git branch -D
experimental'.
% git branch -D experimental
Deleted branch experimental.

blead에 커밋하기 (Committing to blead)

'blead' 브랜치는 Perl의 다음 프로덕션 릴리스가 돼요.

어떠한 로컬 변경이라도 blead에 push하기 전에 몇 가지를 하는 게 믿을 수 없이 중요해요. 그렇지 않으면 다른 커미터들이 쇠스랑과 횃불을 들고 뒤쫓아 올 거예요:

좋은 커밋 메시지가 있는지 확인하세요. 자세한 내용은 "Commit message" in perlhack를 보세요.

테스트 스위트를 실행하세요. 오타 수정 하나가 테스트 파일을 깨뜨릴 거라고 생각하지 않을지도 몰라요. 틀렸어요. 테스트 스위트를 돌리지 않아 문제가 생긴 예시가 있어요. 기존 .t에 테스트 몇 개를 추가하는 패치가 제출됐어요. 다른 건 절대 건드릴 수 없으니 영향을 받는 .t 하나 너머로는 테스트할 필요가 없겠죠, 맞나요? 하지만 제출자의 이메일 주소가 마지막 제출 이후 바뀌었고, 그것 때문에 다른 테스트가 실패했어요. 다음 항목에 나오는 테스트 타깃을 돌렸다면 이 문제를 잡았을 거예요.

전체 테스트 스위트를 돌리지 않는다면 적어도 make test_porting은 하세요. 기본적인 위생(sanity) 검사를 실행할 거예요. 어떤 위생 검사인지 보려면 t/porting을 들여다보세요.

miniperl이나 miniperl용 다른 코드 경로가 있는 코어 루틴에 영향을 주는 변경을 하면 꼭 make minitest를 실행하세요. 이건 전체 테스트 스위트도 잡지 못할 문제를 잡아줘요. perl이 아니라 miniperl 아래에서 테스트 하위 집합을 실행하니까요.

병합과 rebase에 관해 (On merging and rebasing)

'blead' 브랜치에 push되는 단순한 일회성 커밋은 깨끗하게 적용되는 단순한 커밋이어야 해요. 다시 말해 병합 없이 master 저장소에 push할 수 있도록, 작업을 blead의 현재 위치에 대해 커밋했는지 확인해야 해요.

가끔 blead가 여러분이 변경을 빌드·테스트하는 동안 움직일 거예요. 그때 push가 이렇게 거부될 거예요:

To ssh://perl5.git.perl.org/perl.git
 ! [rejected]        blead -> blead (non-fast-forward)
error: failed to push some refs to 'ssh://perl5.git.perl.org/perl.git'
To prevent you from losing history, non-fast-forward updates were
rejected Merge the remote changes (e.g. 'git pull') before pushing
again.  See the 'Note about fast-forwards' section of 'git push --help'
for details.

그럴 때는 작업을 blead의 새 위치에 rebase하면 돼요. 이렇게요(master 저장소 리모트가 "p5p"라고 가정):

% git fetch p5p
% git rebase p5p/blead

커밋이 다시 적용되는 것을 보게 되고, 그러면 안전하게 push할 수 있어요. rebase에 대한 더 많은 정보는 git-rebase(1) 명령 문서에서 찾을 수 있어요.

함께만 의미가 있는 더 큰 커밋 집합이나, 집합의 목적 요약이 도움이 되는 경우에는 병합 커밋을 써야 해요. 토픽 브랜치에서 작업을 수행하고, blead가 움직여 코드가 깨지지 않도록 정기적으로 blead에 대해 rebase해야 해요. 작업을 끝내면 마지막 rebase와 테스트를 수행하세요. 선형 히스토리는 blead의 매 커밋마다 조금씩 잃어버려지지만, 마지막 rebase는 히스토리를 다시 선형으로 만들어 미래 유지보수자가 무슨 일이 있었는지 더 쉽게 보게 해줘요. 이렇게 rebase해요(작업이 committer/somework 브랜치에 있었다고 가정):

% git checkout committer/somework
% git rebase blead

그다음 master에 이렇게 병합할 수 있어요:

% git checkout blead
% git merge --no-ff --no-commit committer/somework
% git commit -a

위 스위치들은 설명이 필요해요. --no-ff는 모든 작업이 blead에 대해 선형으로 적용될 수 있어도 병합 커밋을 여전히 준비하라는 뜻이에요. 이렇게 하면 모든 작업이 사이드 브랜치로 표시되고, 그 모든 커밋이 병합 커밋에 의해 주류 blead로 병합되도록 보장해요.

--no-commit는 병합 커밋이 준비되지만 커밋되지는 않는다는 뜻이에요. 커밋은 실제로 다음 명령을 실행할 때 수행되고, 그러면 커밋을 설명하기 위해 편집기가 열려요. --no-commit 없이는 거의 유용한 메시지도 없이 커밋이 만들어져, 작업 설명의 자리로서의 병합 커밋 가치를 크게 떨어뜨릴 거예요.

병합 커밋을 설명할 때 브랜치의 목적을 설명하고, 이 설명이 최종 릴리스 엔지니어가 다음 perldelta 문서를 검토할 때 아마 쓸 것임을 기억하세요.

이어지는 push가 실패하면 rebase 방법에 주의해야 해요. 만약

% git rebase p5p/blead

또는

% git pull --rebase

을 쓰면, 신중히 만든 병합 커밋을 잃을 거예요! 이것을 피하려면:

% git fetch p5p
% git rebase --rebase-merges p5p/blead

을 쓸 수 있어요. 이러면 병합 커밋을 재생성해요.

(2.18 이전의 더 오래된 git 버전에 갇혔다면 git rebase--rebase-merges 스위치가 없고, 대신 --preserve-merges 스위치를 써야 해요.)

유지보수 버전에 커밋하기 (Committing to maintenance versions)

유지보수 버전은 치명적 버그 수정을 추가할 때만 변경해야 해요. perlpolicy를 보세요.

perl의 유지보수 버전에 커밋하려면 로컬 추적 브랜치를 만들어야 해요:

% git checkout --track -b maint-5.005 origin/maint-5.005

이것은 원격 브랜치 origin/maint-5.005를 추적하는 maint-5.005라는 로컬 브랜치를 만들어요. 그다음 이전처럼 pull·commit·merge·push할 수 있어요.

git cherry-pick 명령을 써서 blead와 다른 브랜치에서 커밋을 cherry-pick할 수도 있어요. 새 커밋 메시지에 원본 커밋의 SHA1을 기록하려면 git cherry-pick-x 옵션을 쓰는 것이 권장돼요.

maint 버전에 어떤 변경을 push하기 전에 위의 "Committing to blead"의 단계를 충족했는지 확인하세요.

변경 테스트에 smoke-me 브랜치 쓰기 (Using a smoke-me branch to test changes)

때로 변경이 직접 사용 가능한 OS에서는 테스트할 수 없는 코드 경로에 영향을 줘서, blead에 커밋하기 전에 다른 OS의 사용자들이 그 변경을 테스트하는 게 현명할 수 있어요.

다행히 변경을 여러 OS에서 smoke-test하게 하는 방법이 있어요: "smoke-me" 브랜치로 push하고 특정 자동 smoke-tester들이 자기 OS 결과를 보고하기를 기다리면 돼요. "smoke-me" 브랜치는 브랜치 이름으로 식별돼요. 구체적으로 github.com에서 보듯 첫 이름 구성요소가 정확히 smoke-me인 로컬 브랜치여야 해요.

이를 위한 절차는 대략 이래요(tonyc의 win32stat라는 smoke-me 브랜치 예시 사용):

먼저 로컬 브랜치를 만들고 그걸로 전환해요:

% git checkout -b win32stat

변경을 만들고 perl을 빌드해 테스트한 뒤, 로컬 브랜치에 커밋해요. 그리고 로컬 브랜치를 원격 smoke-me 브랜치로 push해요:

% git push origin win32stat:smoke-me/tonyc/win32stat

이제 로컬에서 blead로 돌아가:

% git checkout blead

다른 일을 계속하면서 하루 이틀 기다리는 동안 https://perl.develop-help.com/?b=smoke-me/tonyc/win32state에서 smoke-me 브랜치에 보고된 결과를 눈여겨보세요.

모든 게 잘 되면 blead 브랜치를 갱신하고:

% git pull

smoke-me 브랜치를 다시 체크아웃해 blead에 rebase해요:

% git rebase blead win32stat

이제 blead로 돌아가 smoke-me 브랜치를 병합해요:

% git checkout blead
% git merge win32stat

앞에서 설명했듯 smoke-me 브랜치에 변경이 많으면, 위 마지막 명령 대신 다음 명령을 써서 변경 개요를 담은 병합 커밋을 준비해야 해요:

% git merge win32stat --no-ff --no-commit

이제 perl을 빌드하고 (병합된) 변경을 평소처럼 push하기 전에 마지막으로 한 번 테스트해야 해요(이상적으로 전체 테스트 스위트, 그게 안 되면 적어도 t/porting/.t* 테스트):

% git push origin blead

마지막으로 원격 smoke-me 브랜치를 삭제해야 해요:

% git push origin :smoke-me/tonyc/win32stat

(아마 이런 경고가 생길 텐데 무시해도 돼요:

remote: fatal: ambiguous argument
                                 'refs/heads/smoke-me/tonyc/win32stat':
unknown revision or path not in the working tree.
remote: Use '--' to separate paths from revisions

) 그리고 나서 로컬 브랜치를 삭제해요:

% git branch -d win32stat

더 알아보기 (Learn more)