Ich möchte ein Remote-Git-Repository in meinem Arbeits-Git-Repository als Unterverzeichnis davon zusammenführen. Ich möchte, dass das resultierende Repository den zusammengeführten Verlauf der beiden Repositorys enthält und dass jede Datei des zusammengeführten Repositorys ihren Verlauf wie im Remote-Repository beibehält. Ich habe versucht, die Teilbaumstrategie zu verwenden, wie unter Verwenden der Teilbaum-Zusammenführungsstrategie beschrieben , aber nachdem ich dieses Verfahren befolgt habe, haben einzelne Dateien, die von der entfernten stammen, ihren Verlauf nicht beibehalten, obwohl das resultierende Repository tatsächlich den zusammengeführten Verlauf der beiden Repositorys enthält (`git log 'auf einem von ihnen zeigt nur die Meldung" Zusammengeführter Zweig ... ").
Außerdem möchte ich keine Submodule verwenden, da ich nicht mehr möchte, dass die beiden kombinierten Git-Repositorys getrennt sind.
Ist es möglich, ein Remote-Git-Repository in einem anderen als Unterverzeichnis zusammenzuführen, wobei einzelne Dateien aus dem Remote-Repository ihren Verlauf beibehalten?
Vielen Dank für jede Hilfe.
BEARBEITEN: Ich probiere derzeit eine Lösung aus, die Git-Filter-Zweig verwendet, um den zusammengeführten Repository-Verlauf neu zu schreiben. Es scheint zu funktionieren, aber ich muss es noch etwas testen. Ich werde zurückkehren, um über meine Ergebnisse zu berichten.
EDIT 2: In der Hoffnung, ich mache mich klarer, gebe ich die genauen Befehle an, die ich mit der Teilbaumstrategie von git verwendet habe, was zu einem offensichtlichen Verlust des Verlaufs der Dateien des Remote-Repositorys führt. Sei A das Git-Repo, in dem ich gerade arbeite, und B das Git-Repo, das ich als Unterverzeichnis in A aufnehmen möchte. Es hat folgendes getan:
git remote add -f B <url-of-B>
git merge -s ours --no-commit B/master
git read-tree --prefix=subdir/Iwant/to/put/B/in/ -u B/master
git commit -m "Merge B as subdirectory in subdir/Iwant/to/put/B/in."
Nach diesen Befehlen und dem Aufrufen des Verzeichnisses subdir / Iwant / to / put / B / in werden alle Dateien von B angezeigt, aber git log
auf jedem von ihnen wird nur die Festschreibungsmeldung "B als Unterverzeichnis in subdir / Iwant / to / put zusammenführen" angezeigt /Behälter." Ihr Dateiverlauf wie in B geht verloren.
Was zu funktionieren scheint (da ich ein Anfänger auf Git bin, kann ich mich irren) ist das Folgende:
git remote add -f B <url-of-B>
git checkout -b B_branch B/master # make a local branch following B's master
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&subdir/Iwant/to/put/B/in/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
git checkout master
git merge B_branch
Der obige Befehl für filter-branch stammt von git help filter-branch
, in dem ich nur den Subdir-Pfad geändert habe.
gitk
sagt über die Geschichte aus? Ich habe in der Vergangenheit die Zusammenführung von Git-Teilbäumen erfolgreich verwendet. Vielleicht können Sie Ihre genauen Befehle offenlegen? Ich bin mir nicht sicher, ob Git-Filter-Branch der richtige Ansatz ist. Ich könnte empfehlen, git-fast-export und git-fast-import zu versuchen, um eine neue Geschichte zu synthetisieren.gitk
die beiden Repos auf ihren Tipps zusammengeführt und in ihren anfänglichen Commits nicht miteinander verbunden. (Würde es helfen, wenn ich Screenshots der Verlaufsansicht von gitk veröffentliche? Kann ich?) Leider haben einzelne Dateien des Remote-Repositorys ihren Verlauf nicht beibehalten, wenn ich dies im Terminal tuegit log <file-from-remote-repo>
. Ich schaue ingit-fast-export
undgit-fast-import
; Ich bin sehr neu in Git. Ich werde meine Frage bearbeiten, um genau zu zeigen, welche Befehle ich mit dem Git-Teilbaum verwendet habe. Vielen Dank für Ihre Antwort.Antworten:
Nachdem ich die ausführlichere Erklärung erhalten habe, denke ich, dass ich es verstehe, und auf jeden Fall habe ich unten eine Problemumgehung. Insbesondere glaube ich, dass die Erkennung des Umbenennens durch die Zusammenführung des Teilbaums mit --prefix getäuscht wird. Hier ist mein Testfall:
Wir erstellen Git-Verzeichnisse a und b mit jeweils mehreren Commits. Wir führen eine Teilbaumzusammenführung durch und führen dann eine endgültige Festschreibung im neuen Teilbaum durch.
Das Ausführen
gitk
(in z / a) zeigt, dass der Verlauf angezeigt wird, wir können ihn sehen. Laufengit log
zeigt, dass der Verlauf angezeigt wird. Das Betrachten einer bestimmten Datei hat jedoch ein Problem:git log bdir/B
Nun, es gibt einen Streich, den wir spielen können. Mit --follow können wir den Vorbenennungsverlauf einer bestimmten Datei anzeigen.
git log --follow -- B
. Dies ist gut, aber nicht großartig, da der Verlauf der Vorzusammenführung nicht mit der Nachzusammenführung verknüpft werden kann.Ich habe versucht, mit -M und -C zu spielen, aber ich konnte es nicht dazu bringen, einer bestimmten Datei zu folgen.
Ich denke, die Lösung besteht darin, git über die Umbenennung zu informieren, die im Rahmen der Teilbaumzusammenführung stattfinden wird. Leider ist git-read-tree ziemlich pingelig in Bezug auf das Zusammenführen von Teilbäumen, sodass wir ein temporäres Verzeichnis durcharbeiten müssen, aber das kann verschwinden, bevor wir uns verpflichten. Danach können wir die vollständige Geschichte sehen.
Erstellen Sie zunächst ein "A" -Repository und machen Sie einige Commits:
Zweitens erstellen Sie ein "B" -Repository und machen einige Commits:
Und der Trick, damit dies funktioniert : Erzwingen Sie, dass Git die Umbenennung erkennt, indem Sie ein Unterverzeichnis erstellen und den Inhalt in dieses verschieben.
Kehren Sie zum Repository "A" zurück und rufen Sie den Inhalt von "B" ab und führen Sie ihn zusammen:
Um zu zeigen, dass sie jetzt zusammengeführt sind:
Um zu beweisen, dass die gesamte Geschichte in einer verbundenen Kette erhalten bleibt:
Wir erhalten die Historie danach, aber das Problem ist, dass Sie seit diesem Dritten in Schwierigkeiten sind, wenn Sie das alte "b" -Repo tatsächlich beibehalten und gelegentlich daraus verschmelzen (sagen wir, es handelt sich tatsächlich um ein separat verwaltetes Repo eines Drittanbieters) wird die Umbenennung nicht durchgeführt haben. Sie müssen versuchen, neue Änderungen in Ihrer Version von b mit dem Umbenennen zusammenzuführen, und ich befürchte, dass dies nicht reibungslos verläuft. Aber wenn b weggeht, gewinnt man.
quelle
git log --stat
. B. beim Betrachten ). Außerdem hatte ich den--follow
Wechsel in der Dokumentation von Git Log nicht bemerkt . scheint sehr praktisch bei Umbenennungen. Vielen Dank für Ihre ausführliche und informative Antwort!git
davon produziertfatal: refusing to merge unrelated histories
und Sie müssengit merge -s ours --allow-unrelated-histories --no-commit B/master
stattdessen ausführen .git-subtree
ist ein Skript, das genau für diesen Anwendungsfall entwickelt wurde, bei dem mehrere Repositorys unter Beibehaltung des Verlaufs zu einem zusammengeführt werden (und / oder der Verlauf von Teilbäumen aufgeteilt wird, obwohl dies für diese Frage irrelevant zu sein scheint). Es wird seit Release 1.7.11 als Teil des Git-Baums verteilt .Verwenden Sie Folgendes, um ein Repository
<repo>
bei der Revision<rev>
als Unterverzeichnis zusammenzuführen :<prefix>
git subtree add
git-subtree implementiert die Strategie zum Zusammenführen von Teilbäumen benutzerfreundlicher.
Der Nachteil ist, dass im zusammengeführten Verlauf die Dateien nicht fixiert sind (nicht in einem Unterverzeichnis). Angenommen, Sie führen das Repository
a
in einb
. Als Ergebnisgit log a/f1
werden Ihnen alle Änderungen (falls vorhanden) mit Ausnahme derjenigen im zusammengeführten Verlauf angezeigt. Du kannst tun:Dadurch werden jedoch keine anderen Änderungen als in der zusammengeführten Historie angezeigt.
Mit anderen Worten, wenn Sie die
a
Dateien im Repository nicht ändern ,b
müssen Sie--follow
einen nicht festgelegten Pfad angeben . Wenn Sie sie in beiden Repositorys ändern, haben Sie zwei Befehle, von denen keiner alle Änderungen anzeigt.Mehr dazu hier .
quelle
<prefix>
. Zum Beispiel, um ein Unterverzeichnis zusammenzuführen, das irgendwann manuell in ein eigenes Repository verschoben wurde, und um es wieder zusammenzuführen.ich wollte
git log -- file
Arbeit ohne--follow
.Schritt 1 : Schreiben Sie den Verlauf im Quell-Repository neu, damit er so aussieht, als ob alle Dateien immer unterhalb des Unterverzeichnisses vorhanden wären.
Erstellen Sie einen temporären Zweig für den neu geschriebenen Verlauf.
Verwenden Sie dann
git filter-branch
wie unter Wie kann ich den Verlauf neu schreiben, damit sich alle Dateien mit Ausnahme der Dateien, die ich bereits verschoben habe, in einem Unterverzeichnis befinden? ::Schritt 2 : Wechseln Sie zum Ziel-Repository. Fügen Sie das Quell-Repository als Remote im Ziel-Repository hinzu und rufen Sie dessen Inhalt ab.
Schritt 3 : Verwenden Sie
merge --onto
diese Option , um die Commits des neu geschriebenen Quell-Repositorys über dem Ziel-Repository hinzuzufügen.Sie können das Protokoll überprüfen, um festzustellen, ob Sie wirklich das bekommen haben, was Sie wollten.
Schritt 4 : Nach dem Rebase befinden Sie sich im Status "Getrennter KOPF". Sie können den Master schnell auf den neuen Kopf vorspulen.
Schritt 5 : Zum Schluss noch eine Bereinigung: Entfernen Sie die temporäre Fernbedienung.
quelle
git rebase
scheint die angegebenen Optionen nicht zusammen zuzulassen: "Fehler: Interaktive Optionen können nicht kombiniert werden (--interactive, --exec, --rebase-merges, --preserve-merges, --keep-empty, --root + - -onto) mit am Optionen (--committer-Datum-ist-Autor-Datum) "--committer-date-is-author-date
. Die Prüfung auf inkompatible Optionen wurde kürzlich in git v2.19.0 ( github.com/git/git/commit/… ) hinzugefügt . Aus der Beschreibung geht hervor, dass--committer-date-is-author-date
es vorher sowieso still ignoriert wurde.filter-branch
Befehl zu verwendengit filter-repo --to-subdirectory-filter <dir>
, ist er viel schneller und einfacher.Wenn Sie wirklich Dinge zusammennähen möchten, schauen Sie nach. Sie sollten auch verwenden
git rebase --preserve-merges --onto
. Es besteht auch die Möglichkeit, das Autorendatum für die Committer-Informationen beizubehalten.quelle
git filter-branch
und es scheint zu funktionieren, aber vielleicht ist deins besser. Ich werde es ausprobieren.Ich fand die folgende Lösung für mich praktikabel. Zuerst gehe ich in Projekt B und erstelle einen neuen Zweig, in dem bereits alle Dateien in das neue Unterverzeichnis verschoben werden. Ich schiebe dann diesen neuen Zweig zum Ursprung. Als nächstes gehe ich zu Projekt A, füge die Fernbedienung von B hinzu und hole sie, dann checke ich den verschobenen Zweig aus, gehe zurück zum Master und füge zusammen:
Wenn ich in ein Unterverzeichnis gehe
subdir
, kann ich den Verlauf verwendengit log --follow
und habe ihn immer noch.Ich bin kein Git-Experte, daher kann ich nicht sagen, ob dies eine besonders gute Lösung ist oder ob es Vorbehalte gibt, aber bisher scheint alles in Ordnung zu sein.
quelle
Haben Sie versucht, das zusätzliche Repository als Git-Submodul hinzuzufügen? Der Verlauf wird nicht mit dem enthaltenen Repository zusammengeführt, sondern es handelt sich um ein unabhängiges Repository.
Ich erwähne es, weil du es nicht hast.
quelle
Sagen Sie bitte Repository zusammenführen möchten
a
inb
(Ich gehe davon aus sie nebeneinander angeordnet sind):Hierfür müssen Sie
git-filter-repo
installiert haben (filter-branch
wird davon abgeraten ).Ein Beispiel für das Zusammenführen von zwei großen Repositorys, wobei eines davon in einem Unterverzeichnis abgelegt wird: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731
Mehr dazu hier .
quelle