hg-git Klon von Github gibt "abort: repository ist nicht verwandt"

8

Ich habe ein Projekt, dessen Hauptspeicher (Mercurial) sich auf SourceForge befindet, aber es gibt Klone auf Bitbucket (Mercurial) und Github (Git).

Jetzt habe ich hg-git verwendet, um das Mercurial-Repository nach Github zu schieben und was ich von der Vorgehensweise verstehe , einige Metadaten werden dabei im Mercurial-Repository aufbewahrt.

Nun, wenn ich das Bitbucket-Repository erneut cloniere und das Github-Repository neu kloniere, und wenn ich ein hg pull ../github-repo ausspreche, bekomme ich:

%Vor%

Warum ist das und wie kann ich Mercurial überzeugen, dass sie tatsächlich verwandt sind? Oder muss ich mich auf das Original-Repository verlassen, von dem ich ursprünglich nach Github gegangen bin? Ich habe das immer noch, aber angenommen, ich hätte es verloren, was wären die Möglichkeiten, die ich habe, ohne eine manuelle Veränderung der Transplantation?

Hinweis: Der Github-Repo wurde aufgrund einer Pull-Anforderung geändert (neuer Änderungssatz). Aber die SourceForge- und Bitbucket-Repos erkennen einander immer noch als verwandt an. Die Aufgabe besteht nun darin, das Changeset vom Github Git Repo in ein lokales Backup zu ziehen und es zurück zu SourceForge und Bitbucket zu schieben.

    
0xC0000022L 21.06.2013, 17:16
quelle

2 Antworten

9

Das verwandte oder nicht verwandte Bit kommt im Wesentlichen davon, ob zwei Repositories eine gemeinsame Wurzel teilen, d. h. einen anfänglichen Änderungssatz.

Um den Zug zu erzwingen, könntest du mit den Transplantat- oder Transplantationserweiterungen etwas Übelwachsenes tun, aber das könnte Welleneffekte haben, und du scheinst einer solchen Lösung abgeneigt zu sein - ich wäre es auch!

Um zu verstehen, warum Sie ein Problem haben, müssen Sie ein wenig verstehen, wie Hg-Git funktioniert.

Wie Hg-Git funktioniert

tl; dr

Das eigentliche Problem ist, dass Hg-Git grundsätzlich einen neuen Repo dynamisch erstellt. Daher sind die beiden Repositorys nicht miteinander verwandt, da das Produkt von hg convert some-existing-hg-repo nicht mit dem ursprünglichen Repository verknüpft ist. Sie haben es bisher nicht bemerkt, weil Hg-Git das auch in die andere Richtung tut - wenn Sie von einem Mercurial-Repository starten, erstellt es das notwendige Git-Repository. Als Sie mit dem Klonen zu GitHub begonnen haben, haben Sie auf ihren Servern ein reines Git-Repository erstellt, das in jeder Hinsicht mit jedem Repository verbunden ist. Somit ist Ihr Push das neue Git Repo von Hg-Git erstellt und alles funktioniert, kein Problem. Danach haben Sie von diesem Repo gedrängt, also wieder keine Probleme - Hg-Git verfolgt die Beziehung zwischen den lokalen Git- und Hg-Repositories und somit wurde Ihre Beziehung aufrechterhalten. Aber wenn Sie neu beginnen, erstellen Sie ein neues Git und / oder Hg Repo (je nachdem, in welche Richtung Sie gehen) und die Korrespondenz ist gebrochen.

Etwas weniger stark vereinfacht

Hg-Git funktioniert, indem es ein verborgenes Git-Repository erstellt und eine Übereinstimmung zwischen den Commits der Git- und Hg-Repositories herstellt. Hg-Git ist eine Zwei-Wege-Brücke, dh es kann Git-Commits machen und Hg-Commits erzeugen und umgekehrt. Hg-Git erreicht seine Zweisprachigkeit durch die Verwendung einer in Python geschriebenen Git-Bibliothek ( dulwich ) und die Verknüpfung mit Mercurial als Erweiterung. Das bedeutet, dass Hg-Git Git-Repositorys liest und schreibt, ohne dass ein git binary / die Git-Referenzimplementierung installiert sein muss . Hg-Git ist jedoch eine Mercurial-Erweiterung und hängt als solches vom System Mercurial für das Mercurial-Ende der Transaktion sowie von der Benutzerschnittstelle ab. Aus diesem Grund gibt es Bemühungen, die umgekehrte Schnittstelle (Git-Hg und dergleichen) zu erstellen, so dass Git-Benutzer das Git verwenden können, um mit Mercurial zu interagieren.

Ob das Git- oder das Hg-Repository erstellt wird, hängt davon ab, wie das Hybridrepository erstellt wurde. Da Sie von der kanonischen Mercurial-Seite kommen, fangen wir dort an.

Wenn Sie ein Repository auf Github oder Bitbucket erstellen, ist es zunächst leer und ohne Commit und somit mit jedem Repository verbunden - dies ist Teil der Motivation für die Vorgabe, dass kein Initial Commit für die Repository-Erstellung erforderlich ist. (Dies gilt sowohl für Git als auch für Mercurial.) Die Repository-Beziehung basiert auf dem Wurzelknoten. Somit kann jedes Repository in dieses neue Repository verschoben werden. Wenn Sie hg push ssh+git://[email protected]/user/some-git-repo zum ersten Mal ausführen, erstellt Hg-Git ein neues, verborgenes Git-Repository in Ihrem lokalen Ordner und verwendet dann die Git-Protokolle, um zu kommunizieren und die Änderungen an die entfernte Datenbank zu übertragen. Von nun an sollten Sie keine Probleme mehr haben, zwischen den beiden Repositories zu kommunizieren - von der anfänglichen Konvertierung des Wurzelknotens und der Eltern-Kind-Beziehungen ist es möglich, eine Eins-zu-eins-Zuordnung zwischen den Changesets der beiden Repositories zu erreichen. (Das ist nicht ganz richtig, besonders, wenn Sie fortgeschrittenere, idiomatische Funktionen von Git oder Mercurial verwenden, aber es wird für jetzt ausreichen.) Hg-Git verfolgt ein bisschen mehr Informationen als das, ich bin mir ziemlich sicher aus keinem anderen Grund, als die Dinge mit aufeinanderfolgenden Stößen und Zügen zu beschleunigen. Wenn Sie also von einem Mercurial-Klon starten, ist Ihr "Proto-Root" der Mercurial-Root und das Git-Repository wird erstellt und bei Bedarf verwaltet.

Wenn Sie jetzt nicht von einem lokalen Mercurial-Klon, sondern von einem Remote-Git-Klon ausgehen, dann werden Sie tatsächlich fertig machen, indem Sie einen Mercurial-Klon aus dem Git erstellen. Proto-Wurzel "ist die Git-Wurzel. Genauer gesagt, wenn Sie hg clone ssh+git://[email protected]/user/some-git-repo ausführen, startet Mercurial, prüft, ob es eine Schnittstelle mit der Fernbedienung herstellen kann (was es mit Hilfe von Hg-Git tun kann), erstellt dann das Verzeichnis und ruft die erforderliche Erweiterung (en) auf, dh Hg -Git. Hg-Git erstellt dann einen versteckten .git Ordner in Ihrem .hg Ordner, führt einen Git Clone aus und konvertiert dann den Git Repo in einen Mercurial; Sobald dieser Klon vollständig ist, ruft er hg update auf, was direkt auf dem Mercurial-Repo funktioniert, ohne dass etwas über das Git-Repo bekannt ist.

Dies, vermute ich, ist in Ihrem Fall schief gelaufen. Wenn Sie einen neuen Klon von GitHub erstellt haben, haben Sie tatsächlich ein neues Mercurial-Repository erstellt, das natürlich nicht mit Ihrem ursprünglichen Repository zusammenhängt - ähnlich wie das Produkt von hg convert nicht mit dem Original verwandt ist , , auch wenn die mutierten Commits nicht den ursprünglichen enthalten .(Das ist ungefähr so, als wenn Sie etwas in eine andere Sprache übersetzen und wieder zurück, Sie erhalten nicht immer das ursprüngliche Formular zurück.) Aus verschiedenen Gründen vermute ich, dass Hg-Git seine Konvertierungen zeitunabhängig und deterministisch durchführt (fast definitiv letzteres, aber es könnte zusätzliche Metadaten über die Umwandlung selbst hinzufügen, was nicht das erstere bedeuten würde). Wenn dies der Fall ist, sollten Sie in der Lage sein, von einem kanonischen Hg-Klon zu starten und die Verbindung zum Git-Repository neu zu erstellen. (Ja, es ist etwas problematisch, dass die Direktionalität der anfänglichen Konvertierung einen Unterschied macht, aber die Vor- und Nachteile der Design-Entscheidungen, die dazu führen, werden am besten mit den Entwicklern selbst diskutiert.)

Zurück zur Struktur eines hybriden Hg-Git-Repository. Es gibt zwei interessante Dinge hier:

  1. Mercurial ist sich der zusätzlichen Übersetzung, die bei der Kommunikation mit Git-Fernbedienungen und
  2. stattfindet, mehr oder weniger völlig unbewusst
  3. Es gibt ein vollständiges Repository von Git, das nicht sichtbar ist und gelegentlich mit dem Mercurial-Repository synchronisiert wird.

Wichtig ist, dass Sie direkt über Git Git mit dem versteckten Git Repository arbeiten können. Wenn Sie Hg-Git verwenden, wird das Git-Repository nur auf Push-Vorgänge zu und von Remote-Git-Clones synchronisiert, was bedeutet, dass diese lokalen direkten Git-Änderungen nicht mehr mit dem Mercurial-Repository synchron sind - im schlimmsten Fall werden sie ausgeführt ein paar Mal zu Git, dann Commit zu Mercurial ohne zu synchronisieren und effektiv zwei separate Zweige zu erstellen, weil die Hg-Commit und die Git-Commits einen gemeinsamen Vorfahren teilen, aber nicht aufeinander aufbauen. Hg-Git bietet jedoch einen Mechanismus zum manuellen Erzwingen einer Synchronisierung zwischen den Repos über hg gimport [git-repo-to-import-from-if-not-local-hidden] und hg gexport (exportiert standardmäßig zu einer lokalen versteckten Kopie und erstellt sie bei Bedarf). Das Erzwingen dieser Synchronisierung sollte Ihnen auch helfen, die Probleme zu beheben, die Sie bemerkt haben. Sie könnten nämlich Git verwenden, um zu ziehen (oder in Git-Terminologie, fetch - git pull ist gleichbedeutend mit hg pull --update ; git fetch ist hg pull , was den Namen der Mercurial fetch-Erweiterung wirklich unglücklich macht) die neuen changesets in Das Git-Repository verwenden Sie dann hg gimport , um diese Änderungsmengen in das Mercurial-Repository zu importieren.

Nun, wenn Sie etwas wie die Bearbeitung der Historie oder Ähnliches gemacht haben, sind alle Wetten deaktiviert. Ich bin mir nicht sicher, wie Hg-Git damit umgehen würde - ich vermute, es würde Doppelgänger werden. Die neuen Commits im Mercurial-Klon würden zu Git hinzugefügt, aber die gelöschten Changesets befinden sich immer noch im Git-Repo und würden wahrscheinlich wieder in das Mercurial-Repository importiert werden. (Dies ist ein direktes Ergebnis der Hg-Git-Methode der Offline-Synchronisierung von Changesets.) In diesem Fall empfehle ich, ein kanonisches Repository auszuwählen, alle Klone zu löschen und einen neuen Push mit einer Entschuldigung an alle durchzuführen, deren Klone durch dieses Chaos ungültig gemacht wurden. (Dies ist übrigens ein Teil der Gründe, warum die Mercurial-Community so vorsichtig ist, Geschichte zu bearbeiten.)

Mögliche Lösungen

  1. @EmilSit schlug vor, dass Sie hg pull git+ssh://github.com/you/githubrepo.git direkt aus dem canonischen (nicht GitHub-Klon) Mercurial-Repository ausführen. Dies hat eine gute Chance zu arbeiten, wenn man annimmt, dass Hg-Git's Methode, den ersten Git-Klon zu erstellen, vollkommen zeitunabhängig und deterministisch ist. (Letzteres ist fast sicher wahr, aber ich bin mir nicht sicher, ersteres, siehe Text oben für weitere Details.)

  2. Sie können die lokale Variante dazu verwenden: Verwenden Sie git clone ssh://github.com/you/githubrepo.git , um einen lokalen reinen Git-Klon zu erhalten, und führen Sie dann hg pull ../githubrepo aus. (Dazu muss Git installiert sein.) Hg-Git sollte sich automatisch einschalten und die Konvertierung durchführen. Die Konvertierung hängt auch davon ab, dass Hg-Git die Umwandlung in einer deterministischen, zeitunabhängigen Weise durchführt.

  3. Sie können direkt im verborgenen Git-Repository im ursprünglichen Hybrid-Repository arbeiten. Verwenden Sie git fetch (möglicherweise müssen Sie zuerst cd in den Ordner .git , der zuerst im Ordner .hg ausgeblendet wurde). Führen Sie dann hg gimport && hg update aus, um die Änderungen vom git-Repository zu importieren und zu aktualisieren. (Möglicherweise haben Sie den Pfad für gimport - entweder . oder den Pfad zum versteckten Git-Repo angegeben. Ich vermute, Sie könnten auch den GitHub-Pfad angeben.)

  4. Sie können verschiedene Methoden des stummen Umpflanzens - das Exportieren einer Patch-Serie usw. - und das manuelle Commit verwenden. Wenn Sie bei manuellen Commits ein anderes Entwicklerguthaben angeben möchten, können Sie die Option -u verwenden, um den Benutzer pro Commit festzulegen.

  5. Sie können intelligente Transplantationen entweder mit dem Transplantat oder transplant Erweiterungen. Verwenden Sie zunächst Hg-Git, um einen neuen Mercurial-Klon des GitHub-Repositorys zu erstellen. Verwenden Sie dann eine dieser Erweiterungen, um die beiden Mercurial-Repositorys zusammenzubringen.

Mindestens eine der Nicht-Verpflanzungsmethoden sollte funktionieren, denn wenn Hg-Git seine Magie nicht zeitabhängig macht, sollte es möglich sein, eine gemeinsame Wurzel zu finden.Selbst wenn eine gemeinsame Wurzel gefunden wird, können Sie jedoch mit zwei im Grunde genommen Duplikate (unbenannte Zweige) enden, die Sie dann wieder zusammenführen müssen.

    
Livius 30.06.2013 18:06
quelle
1

Ich würde hinzufügen, dass Sie sogar einen "repository related" -Fehler bekommen können, wenn Sie ein hg repo auf git schieben, dann das git repo von hg klonen und dann versuchen, Änderungen vom ursprünglichen hg repo einzufangen. Da wir jetzt ein hg repo lokal aus einem git repo erstellt haben, das aus dem ursprünglichen hg repo erstellt wurde, nehme ich an, dass das lokale und das ursprüngliche hg repo verwandt sein sollten, aber manchmal nicht.

Aufgrund der Unterschiede in der Art und Weise, wie hg und git mit Autornamen und E-Mails umgehen, wenn Ihr ursprüngliches hg-Repo für Autoren etwas anderes als Name <[email protected]> -styles hatte, sehen Sie dieses Problem. Der Grund ist, dass hg-git versucht, Autoren in den strikten Git-Stil zu konvertieren (der die erwähnten Namen-E-Mail-Paare verwendet) und die Lücken ausfüllt, falls dies nicht der Fall ist (siehe die Erklärung in hg-gits Readme: < a href="https://bitbucket.org/durin42/hg-git"> Ссылка ).

So kann es vorkommen, dass der Autor für einen Changeset im ursprünglichen hg repo nicht genau der gleiche ist wie im git repo; und als Ergebnis werden Autoren in dem aus dem git-Repo erzeugten hg-Repo nicht mit denen in dem ursprünglichen hg-Repo übereinstimmen, z.B.:

  1. Änderungssatz A im ursprünglichen hg repo hat den Autor als [email protected] festgelegt.
  2. Da dies nicht dem git-Standard entspricht, konvertiert hg-git dies in [email protected] <[email protected]> im git-Repo.
  3. Jetzt, wenn Sie den Git Repo zu hg klonen, wird der Änderungssatz den Autor als [email protected] <[email protected]> .
  4. haben

Da für zwei Repos, die verwandt werden sollen, das initiale Commit genau übereinstimmen sollte, erhalten Sie den Fehler "repository unrelated", selbst wenn der Hash, die Commit-Nachricht, datetime übereinstimmen, aber der Autor anders ist. Ziemlich schmerzhaft zu erleben (argh, jetzt bin ich bestraft, weil ich vergessen habe, den Autor vor drei Jahren richtig einzustellen!), Aber völlig in Ordnung.

    
Piedone 29.11.2015 19:55
quelle