[Final] PEP 385 - Migrating from Subversion to Mercurial

원문 링크: PEP 385 - Migrating from Subversion to Mercurial

상태: Final 유형: Process 작성일: 25-May-2009

PEP 385 – Subversion에서 Mercurial로 마이그레이션

저자: Dirkjan Ochtman, Antoine Pitrou, Georg Brandl 상태: Final (최종) 유형: Process (절차) 작성일: 2009년 5월 25일

목차

동기

Mercurial DVCS(분산 버전 관리 시스템)로 전환하기로 결정한 후, 실제 마이그레이션이 수행되어야 합니다. Python과 같이 크고 분산된 프로젝트의 버전 관리 시스템처럼 중요한 인프라의 경우, 이는 상당한 노력이 필요합니다. 이 PEP는 추가 논의를 위해 취해야 할 단계를 설명하려는 시도입니다. 이는 SVN으로의 마이그레이션을 논의했던 PEP 347과 다소 유사합니다.

hg를 최대한 활용하기 위해, (a) 가능한 한 많은 SVN 메타데이터를 유지하고, (b) 모든 메타데이터를 Mercurial에서 일반적인 형식으로 변환하는 높은 충실도의 변환을 원합니다. 이 방법으로 Mercurial용으로 작성된 도구를 최적으로 사용할 수 있습니다. 이를 위해 초기 변환에 hgsubversion 소프트웨어를 사용하고자 합니다. 이 hg 확장 기능은 양방향 통신에 사용하기 위해 Subversion에서 Mercurial로의 고품질 변환을 제공하는 데 중점을 두므로, 다른 솔루션만큼 많은 사용 가능한 메타데이터를 버리지 않습니다.

이러한 변환은 저장소의 내용을 재고하고 일부 항목이 여전히 가치가 있는지 판단하기에 좋은 시기이기도 합니다. 이러한 취지에서 다음 섹션에서는 일부 오래된 메타데이터를 폐기할 것을 제안하기도 합니다.

타임라인

전환 마일스톤에 대한 현재 일정은 다음과 같습니다:

  • 2011-02-24: hg.python.org에서 테스트 저장소 사용 가능.
    • Subversion 저장소의 모든 커미터는 테스트 커밋을 허용(및 권장)받게 됩니다.
    • 최종 변환이 완료되면 테스트 저장소 및 모든 테스트 커밋은 제거됩니다.
    • 빌드봇 (buildbot), diff-email, 공백 (whitespace) 검사 통합을 테스트하기 위해 테스트 저장소에 서버 측 훅이 설치될 예정입니다.
  • 2011-03-05: 최종 변환 (잠정).
    • Mercurial에서 유지 관리되는 Subversion 브랜치에 대한 커밋은 차단됩니다.
    • 개발자는 새 저장소로 전환된 후 모든 인프라가 작동하는 것이 확인될 때까지 Mercurial 저장소로 푸시하는 것을 삼가야 합니다.

전환 계획

브랜치 전략

Mercurial은 브랜치를 사용하는 두 가지 기본 방법이 있습니다. 첫 번째는 “클론된 브랜치(cloned branches)”로, 각 브랜치가 별도의 저장소에 유지됩니다. 두 번째는 “이름 있는 브랜치(named branches)”로, 각 리비전이 속한 브랜치를 기록하는 메타데이터를 유지합니다.

  • 클론된 브랜치 (Cloned Branches): 클라이언트에서 더 많은 디스크 공간이 필요하다는 단점이 있지만, 브랜치를 구별하기 더 쉽습니다.
  • 이름 있는 브랜치 (Named Branches): 브랜치 간 전환이 약간 더 쉽지만, 모든 브랜치 이름은 히스토리의 영구적인 부분이 됩니다.

이름 있는 브랜치와 클론된 브랜치의 차이점은 다음과 같습니다:

  • 다른 (유지 보수) 클론의 태그는 로컬 클론에서 사용할 수 없습니다.
  • 이름 있는 브랜치가 있는 클론은 더 많은 데이터를 포함하므로 더 커집니다.

릴리스 브랜치에는 이름 있는 브랜치를 사용하고, 기능 브랜치에는 클론된 브랜치를 채택할 것을 제안합니다.

히스토리 관리

변환으로 인한 정보 손실을 최소화하기 위해, 여러 저장소를 변환 결과로 제공할 것을 제안합니다:

  • “작업(working)” 저장소: 메인라인 트렁크(및 py3k), 그리고 과거 및 현재 유지 보수 브랜치로 잘라낸 저장소입니다. 개발이 계속되는 곳입니다. 이 저장소는 1990년까지 소스 파일을 변경 사항으로 주석을 달고 다른 일반적인 히스토리 탐색 작업을 포함하여 개발 작업에 필요한 모든 히스토리를 가지고 있습니다.
    • 이 저장소의 기본 브랜치는 Subversion에서 py3k로 알려진 것이며, Subversion trunklegacy-trunk라는 브랜치 이름으로 존재하지만 Mercurial에서는 이 브랜치가 닫힙니다.
    • 릴리스 브랜치는 주요 및 부 버전으로 이름이 지정됩니다 (예: 3.2).
  • “히스토리(historic)” 또는 “아카이브(archive)” 저장소: Subversion 저장소(실제로는 /python 하위 디렉토리)의 완전하고 편집되지 않은 변환본을 포함하는 저장소입니다. 읽기 전용 리소스로 제공됩니다.
  • 활성 기능 브랜치당 하나의 추가 저장소: “활성”이란 적어도 한 명의 핵심 개발자가 브랜치 제공을 요청하는 것을 의미합니다. 각 이러한 저장소에는 기능 브랜치와 메인라인(SVN의 trunk 및/또는 py3k에서 오는)의 모든 선조 변경 세트가 포함됩니다.

모든 브랜치가 히스토리 저장소에 존재하므로, 필요하다고 판단되면 언제든지 별도의 저장소로 추출할 수 있습니다.

SVN 리비전 번호, Mercurial 변경 세트 및 SVN 브랜치 이름 간의 최종 리비전 맵은 Misc 디렉토리에 저장된 파일로 제공될 것입니다. 그 형식은 다음과 같습니다:

[...]
88483 e65daae6cf4499a0863cb7645109a4798c28d83e issue10276-snowleopard
88484 835cb57abffeceaff0d85c2a3aa0625458dd3e31 py3k
88485 d880f9d8492f597a030772c7485a34aadb6c4ece release32-maint
88486 0c431b8c22f5dbeb591414c154acb7890c1809df py3k
88487 82cda1f21396bbd10db8083ea20146d296cb630b release32-maint
88488 8174d00d07972d6f109ed57efca8273a4d59302c release27-maint
[...]

태그 변환

SVN tags 디렉토리에는 많은 오래된 내용이 있습니다. 이들 중 일부는 실제로는 완전한 태그가 아니라 저장소의 작은 하위 집합만 포함합니다. 모든 릴리스 태그는 유지됩니다. 다른 태그는 개발자 커뮤니티의 요청에 따라 포함됩니다. 태그 명명 체계를 v3.2.1a2와 같은 형식으로 일관성 있게 만들 것을 제안합니다.

저자 맵

hg에서 일반적인 사용자 이름(예: ‘First Last user@example.org’ 형식)을 제공하기 위해, cvssvn 사용자 이름을 실제 이름과 이메일 주소에 매핑하는 저자 맵(author map)이 필요합니다. 우리는 마이그레이션 도구 저장소에 이러한 맵의 완전한 버전을 가지고 있습니다(주소 수집기에게 유출되는 것을 피하기 위해 공개적으로 접근할 수 없음). 이메일 주소는 오래되었을 수 있지만, 이는 발생할 수밖에 없는 일입니다. 하지만 가능한 한 많은 사람이 오래된 주소를 검토하도록 하는 것이 좋습니다. 현재 버전에는 여전히 일부 인코딩 문제가 있는 것으로 보입니다.

.hgignore 생성

.hgignore 파일은 Mercurial 저장소에서 버전 관리에 적합하지 않은 파일을 무시하는 데 사용될 수 있습니다. 이는 여러 가능한 형태의 패턴 매칭을 사용하여 수행됩니다. 현재 Python 저장소에는 hg 미러를 사용하는 데 도움이 되는 기본적인 .hgignore 파일이 이미 포함되어 있습니다.

현재 Python 저장소에 이미 .hgignore 파일(hg 미러 사용용)이 포함되어 있으므로, 단순히 이를 사용할 것입니다. 파일의 전체 히스토리를 생성하는 것이 논의되었지만, 비실용적이라고 판단되었습니다(오래된 리비전의 경우 무시하는 것이 덜 중요하므로 상대적으로 어렵고 이득이 거의 없기 때문입니다).

저장소 크기

현재 Python 저장소의 단순 변환 결과는 1.9GB입니다. 이는 Subversion 저장소(2.7GB)보다 작지만 실현 가능하지 않습니다.

작업 저장소에 적용된 트리밍(trimming)과 Mercurial 내부 저장소의 레이아웃을 매우 효율적으로 최적화하는 “revlog 재정렬(revlog reordering)” 프로세스를 통해 크기가 더 관리하기 쉬워집니다.

모든 최적화가 완료된 후, 작업 저장소의 크기는 디스크에서 약 180MB입니다. 클론할 때 네트워크를 통해 전송되는 데이터 양은 약 80MB로 추정됩니다.

다른 저장소

svn.python.org의 “projects” 저장소에는 여러 다른 프로젝트가 호스팅되어 있습니다. “peps” 디렉토리는 주요 Python 저장소와 함께 변환될 것입니다. Richard Tew는 Stackless 저장소도 변환되기를 원한다고 밝혔습니다. svn.python.org 저장소의 다른 어떤 프로젝트를 변환해야 할까요?

Jython 저장소를 변환하려는 초기 시도가 있습니다. 불행히도 hgsubversion의 현재 tip은 어느 시점에서 실패합니다. 조사가 진행 중입니다.

Mercurial로 변환되기를 원하는 다른 저장소는 주요 Python 마이그레이션이 완료된 후 저에게 알려주시면, 그들의 요구 사항을 처리할 것입니다.

인프라

hg-ssh

개발자는 현재 설정과 유사하게 ssh를 통해 저장소에 액세스해야 합니다. 공개 키는 hg@ 공유 계정에 대한 액세스 권한을 부여하는 데 사용될 수 있습니다. 또한 hg.python.orghgwebdir 인스턴스가 설정되어 있어 쉬운 브라우징 및 읽기 전용 액세스를 제공합니다. 이는 개발자가 새로운 클론(별도의 저장소에서 개발함으로써 이득을 얻는 장기적인 기능용)을 쉽게 시작할 수 있도록 구성되어 있습니다.

또한, 핵심 개발자를 위한 공개 저장소의 직접 생성도 허용되지만, 어떤 명명 체계가 강제될지는 아직 결정되지 않았습니다:

$ hg init ssh://hg@hg.python.org/sandbox/mywork
repo created, public URL is http://hg.python.org/sandbox/mywork

훅 (Hooks)

현재 여러 훅이 사용 중입니다. 이에 해당하는 hg 훅을 개발하고 배포해야 합니다. 다음 훅들이 사용되고 있습니다:

  • 공백 확인 (check whitespace): 공백이 Python 코드베이스 규칙과 일치하지 않을 경우 커밋을 거부하는 훅입니다. 변경 그룹(changegroup)에서는 tip만 확인됩니다(이는 타사 저장소에서 가져온 변경 사항에 대한 정리 커밋을 허용합니다). 또한 사람들이 사용할 수 있는 클라이언트 측 저장소용 공백 훅을 제공할 수도 있습니다. 이는 공백 문제에 대해 경고하거나 변경된 줄에서 후행 공백을 잘라낼 수 있습니다.
  • 푸시 메일 (push mails): 이메일에는 공개 저장소로 푸시된 각 변경 세트에 대한 diff가 포함되며, 변경 세트를 푸시한 사용자 이름도 포함됩니다(이는 변경 세트에 기록된 저자와 반드시 동일하지는 않습니다).
  • 빌드봇 (buildbots): python.org 빌드 마스터는 cpython 저장소로 푸시된 각 변경 세트에 대해 통지를 받고, 해당 변경 세트가 발생한 브랜치의 모든 빌드 슬레이브에서 적절한 빌드를 트리거합니다.

훅 저장소에는 이러한 서버 측 훅을 Mercurial로 포팅한 버전과 몇 가지 추가 훅이 포함되어 있습니다:

  • 브랜치 헤드 확인 (check branch heads): 기존 브랜치에 새 헤드를 생성하는 푸시를 거부하는 훅입니다. 푸시하는 사용자는 초과 헤드를 병합하고 다시 푸시를 시도해야 합니다.
  • 브랜치 확인 (check branches): 허용된 이름 있는 브랜치에 없는 모든 변경 세트를 거부하는 훅입니다. 이 훅의 화이트리스트는 새 유지 보수 브랜치를 생성할 때 업데이트되어야 합니다.
  • 줄 끝 확인 (check line endings): eol 확장에 기반한 훅으로, 잘못된 줄 끝이 있는 파일을 커밋하는 모든 변경 세트를 거부합니다. 커밋은 제거되고 다시 수행되어야 하며, 커미터의 컴퓨터에서 eol 확장이 활성화되어 있을 수 있습니다.

한 가지 추가 훅도 유용할 수 있습니다:

  • 기여자 확인 (check contributors): 현재 설정에서는 모든 변경 세트에 커미터의 사용자 이름이 있으며, 커미터는 기여자 계약에 서명해야 합니다. 등록된 기여자 목록을 유지하는 경우, 커미터가 기여자인지 확인하는 훅을 사용할 수 있습니다. 그러면 이 훅은 알 수 없는 기여자의 변경 세트를 포함하는 리비전 그룹을 푸시하는 사용자에게 경고할 수 있습니다.

줄 끝 변환 (End-of-line conversions)

Mercurial에서 원래 win32text 확장에 의해 제공되었던 줄 끝 변환 지원 부족에 대한 논의는 Subversion의 svn:eol-style 속성과 유사하게 파일별로 줄 끝 규칙의 버전 관리 지원하는 새로운 eol 확장 개발로 이어졌습니다. 이 정보는 버전 관리되는 .hgeol이라는 파일에 유지되며, 이러한 파일은 이미 Subversion 저장소에 체크인되어 있습니다.

서버 측에도 일관성 없는 개행 데이터를 도입하는 변경 세트를 거부하는 훅이 존재합니다 (위 참조).

hgwebdir

표준에 가까운 hgwebdir 설치가 설정되어야 합니다. Python 웹사이트와 일치하는 스타일을 고안할 수도 있습니다.

Subversion 리비전을 조회하고 주어진 변경 세트에 대한 적절한 hgweb 페이지로 리다이렉션할 수 있는 작은 WSGI 애플리케이션이 작성되었습니다. 이는 변환된 리비전이 어떤 저장소에 있든 상관없이 작동합니다 (하나의 큰 Subversion 저장소가 여러 Mercurial 저장소로 변환되기 때문입니다). 또한 16진수 ID로 Mercurial 변경 세트를 조회할 수도 있습니다.

Roundup

위에서 언급된 조회 스크립트의 URL을 Roundup에 지정함으로써, SVN 리비전에 대한 링크는 계속 작동하며, 저장소 및 변경 세트 ID를 제공할 필요 없이 Mercurial 변경 세트에 대한 링크도 생성할 수 있습니다.

마이그레이션 후

코드 확보 위치

마이그레이션 후, hgwebdirhg.python.org에서 운영될 것입니다. 이는 많은 조직에서 허용된 표준이며, svn.python.org와 쉽게 병행됩니다.

예를 들어, 작업 저장소는 http://hg.python.org/cpython/에, 아카이브 저장소는 http://hg.python.org/cpython-archive/에 있을 수 있습니다. 쓰기 액세스의 경우, 개발자는 ssh를 사용해야 하며, 이는 ssh://hg@hg.python.org/cpython/과 같을 수 있습니다.

code.python.org도 호스트 이름으로 제안되었습니다. 그러나 호스트 이름에 VCS 이름을 사용하는 것이 혼란을 방지하는 데 좋다고 생각합니다. hg.python.orgsvn 또는 bzr를 사용할 수 없다는 것이 명확해야 합니다.

hgwebdir는 이미 모든 변경 세트에 대한 tarball을 제공할 수 있습니다. 이는 일일 스냅샷의 필요성을 없애고, 사용자에게 tip.tar.gz를 가리키게 함으로써 최신 버전을 얻을 수 있도록 합니다. 원한다면 buildbot 결과를 사용하여 마지막으로 성공한 변경 세트를 가리킬 수도 있습니다.

Python 관련 문서

hg는 훌륭한 내장 문서(hg help를 통해 사용 가능)와 유용한 정보 및 레시피로 가득 찬 위키, 그리고 인기 있는 책(온라인에서 읽을 수 있음)을 제공합니다.

그 외에도 최근 개편된 Python Developer’s Guide는 Subversion 대신 Mercurial에 대한 지침이 포함된 브랜치를 이미 가지고 있으며, 이 브랜치의 온라인 빌드도 제공됩니다.

제안된 워크플로우

여러 브랜치 간의 패치 마이그레이션을 위한 두 가지 워크플로우를 제안합니다.

2.x 또는 3.x 브랜치 내에서의 마이그레이션: 패치는 항상 적용될 수 있는 가장 오래된 브랜치에 먼저 커밋될 것을 제안합니다. 그런 다음 결과 변경 세트는 hg merge를 사용하여 해당 시리즈(2.x 또는 3.x) 내의 모든 최신 브랜치로 병합될 수 있습니다.

  • 만약 최신 브랜치에 그대로 적용되지 않는다면, hg revert를 사용하여 쉽게 새 브랜치 네이티브 헤드로 되돌리고, 패치의 다른 버전(또는 적용할 수 없는 경우 없음)을 패치한 다음 병합을 커밋할 수 있습니다.
  • 여기서 전제는 해당 시리즈 내의 오래된 브랜치에서 온 모든 변경 세트가 결국 해당 시리즈 내의 모든 최신 브랜치로 병합된다는 것입니다.

이것은 가장 고통 없는 병합 절차를 제공합니다. 이는 일반적인 경우, 패치를 적용하기 전에 패치가 적용되어야 할 가장 오래된 브랜치에 대해 생각해야 한다는 것을 의미합니다. 일반적으로 이는 최신 유지 보수 브랜치와 트렁크의 두 브랜치 중 하나이며, 보안 수정 전용 모드에서 오래된 브랜치에 적용 가능한 보안 수정은 예외입니다.

3.x에서 2.7 유지 보수 브랜치로 버그 수정 병합: (2.6 및 2.5는 보안 수정 전용 모드이며, 해당 유지 보수는 Subversion 저장소에서 계속됩니다) 변경 세트는 다른 방식으로 이식되어야 합니다(병합되지 않음). transplant 확장, import/export, bundle/unbundle이 모두 잘 작동합니다.

이 접근 방식을 선택하면 3.x가 2.x 브랜치 이후의 모든 히스토리를 가질 필요가 없으므로 클론이 그렇게 크지 않고 병합이 그렇게 복잡하지 않습니다.

Subversion의 미래

마이그레이션 후 Subversion 저장소는 어떻게 될까요? SVN 서버에는 CPython 저장소뿐만 아니라 많은 저장소가 포함되어 있으므로, 모든 프로젝트가 마이그레이션하기를 원하지 않거나 다른 프로젝트의 마이그레이션에 더 오랜 시간이 걸릴 수 있으므로, 한동안 계속 존재할 것입니다. 사람들이 뒤처지는 것을 방지하기 위해, 마이그레이션된 프로젝트를 저장소에서 새 이름의 새 읽기 전용 저장소로 이동하는 것을 고려할 수 있습니다.

빌드 식별

Python은 현재 sys.subversion 튜플을 제공하여 Python 코드가 실행 중인 Python의 정확한 버전을 확인할 수 있도록 합니다. 현재 버전은 다음과 같습니다:

('CPython', 'tags/r262', '71600')
('CPython', 'trunk', '73128M')

C API의 Py_GetBuildInfo()에서도 다른 값이 반환되며, sys.version의 일부로 Python 코드에서 사용할 수 있습니다:

'r262:71600, Jun 2 2009, 09:58:33'
'trunk:73128M, Jun 2 2009, 01:24:14'

리비전 식별자는 hg의 리비전 해시의 짧은 버전(예: 'dd3ebf81af43')이 될 것이며, 빌드된 작업 디렉토리가 수정된 경우 '+'( 'M' 대신)가 추가될 것을 제안합니다. 이는 이러한 종류의 사용을 위한 hg id 명령의 출력을 반영합니다. sys.subversion 값도 VCS의 변경 사항을 반영하여 sys.mercurial로 이름이 변경될 것입니다.

태그/브랜치 식별자의 경우, hg는 현재 체크아웃된 리비전에 태그가 있는지 확인하고, 태그가 있다면 태그를 사용하며('tip'은 제외), 그렇지 않으면 브랜치 이름을 사용할 것을 제안합니다. sys.subversion은 다음과 같이 됩니다:

('CPython', 'v2.6.2', 'dd3ebf81af43')
('CPython', 'default', 'af694c6a888c+')

그리고 빌드 정보 문자열은 다음과 같이 됩니다:

'v2.6.2:dd3ebf81af43, Jun 2 2009, 09:58:33'
'default:af694c6a888c+, Jun 2 2009, 01:24:14'

이는 hg의 기본 브랜치가 Subversion의 'trunk' 대신 'default'로 불린다는 것과 제안된 새 태그 형식을 반영합니다.

Mercurial은 또한 최신 태그와 현재 변경 세트와 해당 태그 사이의 변경 세트 수를 알아내어 설명적인 버전 문자열을 제공할 수 있습니다:

$ hg parent --template "{latesttag}+{latesttagdistance}-{node|short}\n"
v3.2+37-4b5d0d260e72
$ hg up 2.7
3316 files updated, 0 files merged, 379 files removed, 0 files unresolved
$ hg parent --template "{latesttag}+{latesttagdistance}-{node|short}\n"
v2.7.1+216-9619d21d8198

각주

Mercurial 책은 이름 있는 브랜치의 사용을 권장하지 않지만, 이 점에서는 다소 오래되었습니다. hg의 개선으로 인해 해당 언급이 작성된 이후 이름 있는 브랜치는 사용하기 훨씬 쉬워졌습니다. 초기 작업 저장소는 아카이브 저장소의 하위 집합이므로, 작업 저장소에서 아카이브 저장소로 주기적으로 변경 사항을 가져오는 것도 가능합니다.

저작권

이 문서는 퍼블릭 도메인에 공개되었습니다.


Source: https://github.com/python/peps/blob/main/peps/pep-0385.rst Last modified: 2025-02-01 08:59:27 GMT

⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.

Comments