PEP 385 – Migration von Subversion zu Mercurial
- Autor:
- Dirkjan Ochtman <dirkjan at ochtman.nl>, Antoine Pitrou <solipsis at pitrou.net>, Georg Brandl <georg at python.org>
- Status:
- Final
- Typ:
- Prozess
- Erstellt:
- 25-Mai-2009
Inhaltsverzeichnis
Motivation
Nachdem die Entscheidung getroffen wurde, auf das DVCS Mercurial umzusteigen, muss die eigentliche Migration noch durchgeführt werden. Im Falle einer wichtigen Infrastrukturkomponente wie des Versionskontrollsystems für ein großes, verteiltes Projekt wie Python ist dies ein erheblicher Aufwand. Dieses PEP versucht, die Schritte zu beschreiben, die für eine weitere Diskussion unternommen werden müssen. Es ähnelt in gewisser Weise PEP 347, das die Migration zu SVN diskutierte.
Um das Beste aus hg herauszuholen, möchten wir eine hochgradig detailgetreue Konvertierung durchführen, so dass (a) so viel wie möglich von den svn-Metadaten beibehalten wird und (b) alle Metadaten in Formate konvertiert werden, die in Mercurial üblich sind. Auf diese Weise können für Mercurial geschriebene Werkzeuge optimal genutzt werden. Um dies zu erreichen, wollen wir die hgsubversion Software für eine anfängliche Konvertierung verwenden. Diese hg-Erweiterung konzentriert sich darauf, eine qualitativ hochwertige Konvertierung von Subversion nach Mercurial für die Zwei-Wege-Kommunikation bereitzustellen, was bedeutet, dass nicht so viele verfügbare Metadaten weggeworfen werden wie bei anderen Lösungen.
Eine solche Konvertierung scheint auch ein guter Zeitpunkt zu sein, um den Inhalt des Repositories zu überdenken und zu entscheiden, ob einige Dinge noch wertvoll sind. In diesem Sinne schlagen die folgenden Abschnitte auch das Verwerfen einiger älterer Metadaten vor.
Zeitplan
Der aktuelle Zeitplan für die Meilensteine der Konvertierung
- 24.02.2011: Verfügbarkeit eines Test-Repos unter hg.python.org
Test-Commits werden von allen Committern des Subversion-Repositories zugelassen (und ermutigt). Das Test-Repository und alle Test-Commits werden nach Abschluss der endgültigen Konvertierung entfernt. Die serverseitigen Hooks werden für das Test-Repository installiert, um die Integration von buildbot, diff-email und Whitespace-Prüfung zu testen.
- 05.03.2011: Endgültige Konvertierung (vorläufig)
Commits in die Subversion-Branches, die nun in Mercurial gepflegt werden, werden blockiert. Entwickler sollten davon absehen, in die Mercurial-Repositories zu pushen, bis sichergestellt ist, dass die gesamte Infrastruktur nach ihrem Wechsel zum neuen Repository funktioniert.
Übergangsplan
Branch-Strategie
Mercurial hat zwei grundlegende Möglichkeiten, Branches zu nutzen: geklonte Branches, bei denen jeder Branch in einem separaten Repository gehalten wird, und benannte Branches, bei denen jede Revision Metadaten enthält, die angibt, zu welchem Branch sie gehört. Erstes macht es einfacher, Branches zu unterscheiden, auf Kosten von mehr Speicherplatz auf dem Client. Letzteres erleichtert den Wechsel zwischen Branches etwas, aber alle Branch-Namen sind ein permanenter Teil der Historie. [1]
Unterschiede zwischen benannten Branches und geklonten Branches
- Tags in einem anderen (Wartungs-)Klon sind im lokalen Klon nicht verfügbar
- Klone mit benannten Branches werden größer sein, da sie mehr Daten enthalten
Wir schlagen vor, benannte Branches für Release-Branches zu verwenden und geklonte Branches für Feature-Branches zu übernehmen.
Historienverwaltung
Um den Informationsverlust durch die Konvertierung zu minimieren, schlagen wir vor, mehrere Repositories als Konvertierungsergebnis bereitzustellen
- Ein auf den Haupttrunk (und py3k) sowie vergangene und aktuelle Wartungs-Branches reduziertes Repository – dies wird als „Arbeits“-Repository bezeichnet und ist der Ort, an dem die Entwicklung fortgesetzt wird. Dieses Repository enthält die gesamte Historie, die für die Entwicklungsarbeit benötigt wird, einschließlich der Annotation von Quellcode-Dateien mit Änderungen bis zurück ins Jahr 1990 und anderer gängiger History-Mining-Operationen.
Der
default-Branch in diesem Repository ist das, was in Subversion alspy3kbekannt ist, während der Subversion-Trunk unter dem Branch-Namenlegacy-trunkweiterlebt; in Mercurial wird dieser Branch jedoch geschlossen. Release-Branches werden nach ihrer Haupt.Nebenversion benannt, z. B.3.2. - Ein Repository mit der vollständigen, unveränderten Konvertierung des Subversion-Repositories (genauer gesagt, seines /python-Unterverzeichnisses) – dies wird als „historisches“ oder „Archiv“-Repository bezeichnet und als schreibgeschützte Ressource angeboten. [2]
- Ein weiteres Repository pro aktivem Feature-Branch; „aktiv“ bedeutet, dass mindestens ein Kernentwickler die Bereitstellung des Branches wünscht. Jedes solche Repository enthält sowohl den Feature-Branch als auch alle Vorfahren-Changesets vom Hauptzweig (vom
trunkund/oderpy3kin SVN).
Da alle Branches im historischen Repository vorhanden sind, können sie jederzeit separat als Repositories extrahiert werden, falls dies notwendig wird.
Die endgültige Revisionszuordnung zwischen SVN-Revisionsnummern, Mercurial-Changesets und SVN-Branch-Namen wird in einer Datei im Verzeichnis Misc gespeichert. Sein Format ist wie folgt
[...]
88483 e65daae6cf4499a0863cb7645109a4798c28d83e issue10276-snowleopard
88484 835cb57abffeceaff0d85c2a3aa0625458dd3e31 py3k
88485 d880f9d8492f597a030772c7485a34aadb6c4ece release32-maint
88486 0c431b8c22f5dbeb591414c154acb7890c1809df py3k
88487 82cda1f21396bbd10db8083ea20146d296cb630b release32-maint
88488 8174d00d07972d6f109ed57efca8273a4d59302c release27-maint
[...]
Generieren von .hgignore
Die Datei .hgignore kann in Mercurial-Repositories verwendet werden, um Dateien zu ignorieren, die nicht zur Versionskontrolle gehören. Dies geschieht durch verschiedene Musterabgleichsformen. Das aktuelle Python-Repository enthält bereits eine rudimentäre .hgignore-Datei zur Unterstützung von hg-Spiegeln.
Da das aktuelle Python-Repository bereits eine .hgignore-Datei enthält (zur Verwendung mit hg-Spiegeln), werden wir diese einfach verwenden. Die vollständige Historie der Datei wurde diskutiert, aber für unpraktikabel gehalten (da es relativ schwierig mit relativ geringem Gewinn ist, da das Ignorieren für ältere Revisionen weniger wichtig ist).
Repository-Größe
Ein reines Konvertierungsergebnis des aktuellen Python-Repositories wiegt 1,9 GB; obwohl dies kleiner ist als das Subversion-Repository (2,7 GB), ist es nicht praktikabel.
Die Größe wird durch die Beschneidung des Arbeits-Repositories und einen Prozess namens „Revlog-Neuanordnung“, der das Layout des internen Mercurial-Speichers sehr effizient optimiert, handhabbarer.
Nach allen Optimierungen beträgt die Größe des Arbeits-Repositories etwa 180 MB auf der Festplatte. Die über das Netzwerk übertragene Datenmenge beim Klonen wird auf etwa 80 MB geschätzt.
Andere Repositories
Es gibt eine Reihe anderer Projekte, die in svn.python.orgs „projects“-Repository gehostet werden. Das Verzeichnis „peps“ wird zusammen mit dem Haupt-Python-Verzeichnis konvertiert. Richard Tew hat angedeutet, dass er auch das Stackless-Repository konvertiert haben möchte. Welche anderen Projekte im svn.python.org-Repository sollten konvertiert werden?
Es gibt nun einen ersten Versuch, das Jython-Repository zu konvertieren. Die aktuelle Spitze von hgsubversion schlägt leider an einem Punkt fehl. Ausstehende Untersuchung.
Andere Repositories, die nach Mercurial konvertiert werden möchten, können sich nach Abschluss der Haupt-Python-Migration bei mir melden, und ich werde mich um ihre Bedürfnisse kümmern.
Infrastruktur
hg-ssh
Entwickler sollten über SSH auf die Repositories zugreifen, ähnlich wie bei der aktuellen Einrichtung. Öffentliche Schlüssel können verwendet werden, um Personen Zugang zu einem gemeinsamen hg@-Konto zu gewähren. Eine hgwebdir-Instanz wurde auch unter hg.python.org eingerichtet, um einfaches Browsen und schreibgeschützten Zugriff zu ermöglichen. Sie ist so konfiguriert, dass Entwickler trivial neue Klone starten können (für längerfristige Features, die von der Entwicklung in einem separaten Repository profitieren).
Auch die direkte Erstellung öffentlicher Repositories ist für Kernentwickler erlaubt, obwohl noch nicht entschieden ist, welches Namensschema erzwungen wird.
$ hg init ssh://hg@hg.python.org/sandbox/mywork
repo created, public URL is http://hg.python.org/sandbox/mywork
Hooks
Eine Reihe von Hooks ist derzeit in Gebrauch. Die hg-Äquivalente hierfür sollten entwickelt und bereitgestellt werden. Die folgenden Hooks werden verwendet:
- Whitespace-Prüfung: ein Hook, der Commits ablehnt, falls der Whitespace nicht den Regeln für den Python-Codebase entspricht. In einer Change-Gruppe wird nur die Spitze geprüft (dies ermöglicht Bereinigungs-Commits für Änderungen, die aus Drittanbieter-Repos übernommen wurden). Wir können auch einen Whitespace-Hook für clientseitige Repositories anbieten, die Leute nutzen können; er könnte entweder auf Whitespace-Probleme hinweisen und/oder nachgestellte Leerzeichen aus geänderten Zeilen abschneiden.
- Push-Mails: E-Mails enthalten Diffs für jedes Changeset, das in das öffentliche Repository gepusht wird, einschließlich des Benutzernamens, der die Changesets gepusht hat (dies ist nicht unbedingt dasselbe wie der im Changeset aufgezeichnete Autor).
- Buildbots: Der Python.org-Build-Master wird über jedes Changeset informiert, das in das
cpython-Repository gepusht wird, und löst einen entsprechenden Build auf jedem Build-Slave für den Branch aus, in dem das Changeset auftritt.
Das Hooks-Repository enthält Portierungen dieser serverseitigen Hooks zu Mercurial sowie einige zusätzliche Hooks.
- Prüfen von Branch-Köpfen: Ein Hook, der Pushes ablehnt, die einen neuen Kopf auf einem bestehenden Branch erstellen. Der Pusher muss dann die überschüssigen Köpfe zusammenführen und erneut versuchen zu pushen.
- Prüfen von Branches: Ein Hook, der alle Changesets ablehnt, die sich nicht auf einem erlaubten benannten Branch befinden. Die Whitelist dieses Hooks muss aktualisiert werden, wenn wir neue Wartungs-Branches erstellen wollen.
- Prüfen von Zeilenenden: Ein Hook, basierend auf der EolExtension, der alle Changesets ablehnt, die Dateien mit falschen Zeilenenden committen. Die Commits müssen dann gestrippt und erneut durchgeführt werden, möglicherweise mit aktivierter EolExtension auf dem Computer des Committers.
Ein zusätzlicher Hook könnte von Vorteil sein
- Prüfen von Mitwirkenden: In der aktuellen Einrichtung tragen alle Changesets den Benutzernamen von Committtern, die die Einverständniserklärung unterzeichnet haben müssen. Wir möchten vielleicht einen Hook verwenden, um zu prüfen, ob der Committer ein Mitwirkender ist, wenn wir eine Liste registrierter Mitwirkender führen. Dann könnte der Hook Benutzer warnen, die eine Gruppe von Revisionen mit Changesets von unbekannten Mitwirkenden pushen.
End-of-Line-Konvertierungen
Diskussionen über den mangelnden Support für Zeilenende-Konvertierung in Mercurial, der ursprünglich von der win32text extension bereitgestellt wurde, führten zur Entwicklung der neuen eol extension, die eine versionierte Verwaltung von Zeilenende-Konventionen dateiweise unterstützt, ähnlich den svn:eol-style-Eigenschaften von Subversion. Diese Informationen werden in einer versionierten Datei namens .hgeol gespeichert, und eine solche Datei wurde bereits in das Subversion-Repository eingecheckt.
Ein serverseitiger Hook lehnt auch jeden Changeset ab, der inkonsistente Zeilenendedaten einführt (siehe oben).
hgwebdir
Eine mehr oder weniger Standard-hgwebdir-Installation sollte eingerichtet werden. Wir könnten einen Stil entwerfen, der zur Python-Website passt.
Eine kleine WSGI-Anwendung wurde geschrieben, die Subversion-Revisionen nachschlagen und zur entsprechenden hgweb-Seite für den gegebenen Changeset weiterleiten kann, unabhängig davon, in welchem Repository die konvertierte Revision gelandet ist (da ein großes Subversion-Repository in mehrere Mercurial-Repositories konvertiert wird). Sie kann auch Mercurial-Changesets anhand ihrer hexadezimalen ID nachschlagen.
roundup
Indem Roundup auf die URL des oben erwähnten Lookup-Skripts zeigt, werden Links zu SVN-Revisionen weiterhin funktionieren, und Links zu Mercurial-Changesets können ebenfalls erstellt werden, ohne dass Repository- *und* Changeset-ID angegeben werden müssen.
Nach der Migration
Wo man Code bekommt
Nach der Migration wird hgwebdir unter hg.python.org leben. Dies ist ein akzeptierter Standard für viele Organisationen und eine einfache Parallele zu svn.python.org. Das Arbeits-Repository könnte beispielsweise unter http://hg.python.org/cpython/ leben, das Archiv-Repository unter http://hg.python.org/cpython-archive/. Für Schreibzugriff müssen Entwickler SSH verwenden, was ssh://hg@hg.python.org/cpython/ sein könnte.
code.python.org wurde auch als Hostname vorgeschlagen. Wir denken, dass die Verwendung des VCS-Namens im Hostnamen gut ist, da er Verwechslungen vermeidet: Es sollte klar sein, dass man svn oder bzr nicht für hg.python.org verwenden kann.
hgwebdir kann für jeden Changeset bereits Tarballs bereitstellen. Dies macht tägliche Snapshots überflüssig; wir können Benutzer stattdessen auf tip.tar.gz verweisen, was bedeutet, dass sie die neueste Version erhalten. Wenn gewünscht, könnten wir sogar Buildbot-Ergebnisse verwenden, um auf den letzten funktionierenden Changeset zu verweisen.
Python-spezifische Dokumentation
hg kommt mit guter integrierter Dokumentation (verfügbar über hg help) und einem Wiki, das voller nützlicher Informationen und Rezepte ist, ganz zu schweigen von einem beliebten Buch (online lesbar).
Darüber hinaus enthält die kürzlich überarbeitete Python Developer's Guide bereits einen Branch mit Anweisungen für Mercurial anstelle von Subversion; ein Online-Build dieses Branches ist ebenfalls verfügbar.
Vorgeschlagener Workflow
Wir schlagen zwei Workflows für die Migration von Patches zwischen verschiedenen Branches vor.
Für die Migration innerhalb von 2.x- oder 3.x-Branches schlagen wir vor, dass ein Patch immer in den ältesten Branch committet wird, in dem er zuerst angewendet werden kann. Dann kann der resultierende Changeset mit hg merge in alle neueren Branches innerhalb dieser Serie (2.x oder 3.x) gemerged werden. Wenn er sich nicht ohne weiteres auf den neueren Branch anwenden lässt, kann hg revert verwendet werden, um einfach zum nativen Kopf des neuen Branches zurückzukehren, dort eine alternative Version des Patches (oder keine, wenn er nicht anwendbar ist) einzupflegen und dann den Merge zu committen. Die Prämisse ist hier, dass alle Changesets aus einem älteren Branch innerhalb der Serie letztendlich in alle neueren Branches innerhalb der Serie gemerged werden.
Das Ergebnis ist, dass dies das reibungsloseste Merge-Verfahren ermöglicht. Das bedeutet, dass man im Allgemeinen den ältesten Branch bedenken muss, auf den der Patch angewendet werden soll, bevor man ihn tatsächlich anwendet. Normalerweise sind dies nur zwei Branches: der neueste Wartungs-Branch und der Trunk, außer für Sicherheitspatches, die auf ältere Branches im Nur-Sicherheitsfix-Modus zutreffen.
Für das Mergen von Bugfixes aus der 3.x-Reihe in den 2.7-Wartungs-Branch (2.6 und 2.5 befinden sich im Nur-Sicherheitsfix-Modus und ihre Wartung wird im Subversion-Repository fortgesetzt), sollten Changesets transplantiert (nicht gemerged) werden. Die Transplant-Erweiterung, Import/Export und Bundle/Unbundle funktionieren hier gleichermaßen gut.
Die Wahl dieses Ansatzes ermöglicht es 3.x, nicht die gesamte 2.x-Historie seit dem Aufteilung zu tragen, was bedeutet, dass der Klon nicht so groß ist und die Merges nicht so kompliziert sind.
Die Zukunft von Subversion
Was passiert mit den Subversion-Repositories nach der Migration? Da der SVN-Server eine Reihe von Repositories enthält, nicht nur das CPython-Repository, wird er wahrscheinlich noch eine Weile bestehen bleiben, da nicht jedes Projekt migrieren möchte oder es für andere Projekte länger dauert. Um zu verhindern, dass Leute zurückbleiben, möchten wir vielleicht migrierte Projekte aus dem Repository in ein neues, schreibgeschütztes Repository mit einem neuen Namen verschieben.
Build-Identifikation
Python stellt derzeit das Tupel sys.subversion bereit, damit Python-Code genau herausfinden kann, gegen welche Version von Python er läuft. Die aktuelle Version sieht ungefähr so aus
- (‘CPython’, ‘tags/r262’, ‘71600’)
- (‘CPython’, ‘trunk’, ‘73128M’)
Ein anderer Wert wird von Py_GetBuildInfo() in der C-API zurückgegeben und ist für Python-Code als Teil von sys.version verfügbar
- ‘r262:71600, 2. Juni 2009, 09:58:33’
- ‘trunk:73128M, 2. Juni 2009, 01:24:14’
Ich schlage vor, dass der Revisionsbezeichner die Kurzversion des Mercurial-Revisions-Hashes ist, zum Beispiel „dd3ebf81af43“, ergänzt mit „+“ (anstelle von „M“), wenn das Arbeitsverzeichnis, aus dem er gebaut wurde, modifiziert wurde. Dies spiegelt die Ausgabe des hg id-Befehls wider, der für diese Art der Nutzung gedacht ist. Der sys.subversion-Wert wird ebenfalls in sys.mercurial umbenannt, um die Änderung des VCS widerzuspiegeln.
Für den Tag/Branch-Identifier schlage ich vor, dass hg nach Tags an der aktuell ausgecheckten Revision sucht, den Tag verwendet, wenn einer vorhanden ist (‚tip‘ zählt nicht), und andernfalls den Branch-Namen verwendet. sys.subversion wird zu
- (‘CPython’, ‘v2.6.2’, ‘dd3ebf81af43’)
- (‘CPython’, ‘default’, ‘af694c6a888c+’)
und die Build-Info-String wird
- ‘v2.6.2:dd3ebf81af43, 2. Juni 2009, 09:58:33’
- ‘default:af694c6a888c+, 2. Juni 2009, 01:24:14’
Dies spiegelt wider, dass der Standard-Branch in hg „default“ statt „trunk“ von Subversion heißt, und spiegelt das vorgeschlagene neue Tag-Format wider.
Mercurial ermöglicht es auch, den letzten Tag und die Anzahl der Changesets zu ermitteln, die das aktuelle Changeset von diesem Tag trennen, was eine aussagekräftige Versionszeichenfolge ermöglicht.
$ 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
Fußnoten
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0385.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT