Ich habe ein Git-Repository in einem Ordner namens XXX und ich habe ein zweites Git-Repository namens YYY .
Ich möchte das XXX- Repository als Unterverzeichnis mit dem Namen ZZZ in das JJJ- Repository importieren und den gesamten Änderungsverlauf von XXX zu JJJ hinzufügen .
Ordnerstruktur vor:
├── XXX
│ ├── .git
│ └── (project files)
└── YYY
├── .git
└── (project files)
Ordnerstruktur nach:
YYY
├── .git <-- This now contains the change history from XXX
├── ZZZ <-- This was originally XXX
│ └── (project files)
└── (project files)
Kann das gemacht werden oder muss ich auf Submodule zurückgreifen?
Antworten:
Der wahrscheinlich einfachste Weg wäre, das XXX- Zeug in einen Zweig in YYY zu ziehen und es dann in master zusammenzuführen:
In JJJ :
Ich habe das gerade mit ein paar meiner Repos versucht und es funktioniert. Im Gegensatz zu Jörgs Antwort können Sie das andere Repo nicht weiter verwenden, aber ich glaube, Sie haben das sowieso nicht angegeben.
Hinweis: Da dies ursprünglich im Jahr 2009 geschrieben wurde, hat git die in der Antwort unten erwähnte Zusammenführung von Teilbäumen hinzugefügt. Ich würde diese Methode wahrscheinlich heute verwenden, obwohl diese Methode natürlich immer noch funktioniert.
quelle
git mv $(ls|grep -v <your foldername>) <your foldername>/
Dies kopiert alle Dateien und Ordner in Ihren neuen OrdnerWenn Sie den genauen Festschreibungsverlauf des zweiten Repositorys beibehalten und daher auch in Zukunft problemlos Upstream-Änderungen zusammenführen möchten, finden Sie hier die gewünschte Methode. Dies führt dazu, dass der unveränderte Verlauf des Teilbaums in Ihr Repo importiert wird, plus ein Zusammenführungs-Commit, um das zusammengeführte Repository in das Unterverzeichnis zu verschieben.
Sie können Upstream-Änderungen folgendermaßen verfolgen:
Git findet selbst heraus, wo sich die Wurzeln befinden, bevor die Zusammenführung durchgeführt wird, sodass Sie das Präfix bei nachfolgenden Zusammenführungen nicht angeben müssen.
Der Nachteil ist, dass im zusammengeführten Verlauf die Dateien nicht fixiert sind (nicht in einem Unterverzeichnis). Als Ergebnis
git log ZZZ/a
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
ZZZ
Dateien im Repository nicht ändern ,XXX
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.Git-Versionen vor 2.9 : Sie müssen die
--allow-unrelated-histories
Option nicht an übergebengit merge
.Die Methode in der anderen Antwort, die
read-tree
denmerge -s ours
Schritt verwendet und überspringt, unterscheidet sich effektiv nicht vom Kopieren der Dateien mit cp und Festschreiben des Ergebnisses.Die ursprüngliche Quelle war der Hilfeartikel "Subtree Merge" von github . Und noch ein nützlicher Link .
quelle
git log
von mir eingezogenen Dateien durchführe, sehe ich nur das Commit für die einzelne Zusammenführung und nichts von seinem vorherigen Leben im anderen Repo? Git 1.8.0git log -- myfile
anstelle vongit log -- rack/myfile
--allow-unrelated-histories
wenn Sie die Zusammenführung durchführen.git-subtree
ist ein Skript, das genau für diesen Anwendungsfall entwickelt wurde, bei dem mehrere Repositorys zu einem zusammengeführt werden, während der Verlauf beibehalten wird (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.
Für Ihren Fall würden Sie im Repository JJJ Folgendes ausführen:
Der Nachteil ist, dass im zusammengeführten Verlauf die Dateien nicht fixiert sind (nicht in einem Unterverzeichnis). Als Ergebnis
git log ZZZ/a
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
ZZZ
Dateien im Repository nicht ändern ,XXX
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
git subtree add -P name-of-desired-prefix ~/location/of/git/repo-without-.git branch-name
Es gibt eine bekannte Instanz davon im Git-Repository selbst, die in der Git-Community zusammenfassend als " die coolste Zusammenführung aller Zeiten " bezeichnet wird (nach der Betreffzeile, die Linus Torvalds in der E-Mail an die Git-Mailingliste verwendet hat, die dies beschreibt verschmelzen). In diesem Fall war die
gitk
Git-GUI, die jetzt Teil von Git ist, eigentlich ein separates Projekt. Linus hat es geschafft, dieses Repository auf diese Weise mit dem Git-Repository zusammenzuführengit pull
bearbeitet werden.Die E-Mail die Schritte enthält zum Reproduzieren benötigt, aber es ist nicht für schwache Nerven: Erstens, Linus schrieb Git, so dass er wahrscheinlich ein bisschen mehr darüber weiß als du oder ich, und zweitens, das fast 5 Jahren war vor und Git hat sich seitdem erheblich verbessert , vielleicht ist es jetzt viel einfacher.
Insbesondere denke ich, dass man heutzutage in diesem speziellen Fall ein Gitk-Submodul verwenden würde.
quelle
git-subtree
Tool von Drittanbietern , das Ihnen dabei helfen kann: github.com/apenwarr/git-subtreesubtree
Zusammenführungsstrategie, insbesondere in Verbindung mit demgit-subtree
Tool, ist eine nette, vielleicht sogar überlegene Alternative zu Submodulen.Der einfache Weg, dies zu tun, ist die Verwendung des Git-Format-Patches.
Angenommen, wir haben 2 Git-Repositories foo und bar .
foo enthält:
Bar enthält:
und wir wollen mit foo enden, das die Bar enthält und diese Dateien enthält:
Also, um das zu tun:
Und wenn wir alle Nachrichten-Commits von bar neu schreiben möchten, können wir dies tun, z. B. unter Linux:
Dadurch wird am Anfang jeder Festschreibungsnachricht "[bar]" hinzugefügt.
quelle
git am
schlägt dies wahrscheinlich fehl.[ ]
aus der Commit-Nachricht. Sie sollten also einen anderen Marker verwenden als[bar]
Diese Funktion klont das Remote-Repo in das lokale Repo-Verzeichnis. Nach dem Zusammenführen werden alle Commits gespeichert und
git log
die ursprünglichen Commits und die richtigen Pfade angezeigt:Wie benutzt man:
Wenn Sie ein wenig Änderungen vornehmen, können Sie sogar Dateien / Verzeichnisse von zusammengeführtem Repo in verschiedene Pfade verschieben, zum Beispiel:
Hinweise
Pfade werden über ersetzt.
sed
Stellen Sie daher sicher, dass sie nach dem Zusammenführen in den richtigen Pfaden verschoben wurden.Der
--allow-unrelated-histories
Parameter existiert nur seit git> = 2.9.quelle
gnu-sed
damit diegit-add-repo
Funktion funktioniert. Nochmals vielen Dank Andrey!Basierend auf diesem Artikel hat die Verwendung von Teilbaum für mich funktioniert und nur die zutreffende Historie wurde übertragen. Hier posten, falls jemand die Schritte benötigt (stellen Sie sicher, dass Sie die Platzhalter durch die für Sie zutreffenden Werte ersetzen):
Teilen Sie den Unterordner in Ihrem Quell-Repository in einen neuen Zweig auf
git subtree split --prefix=<source-path-to-merge> -b subtree-split-result
in Ihrem Ziel-Repo im Zweig für geteilte Ergebnisse zusammenführen
Überprüfen Sie Ihre Änderungen und legen Sie fest
Vergiss es nicht
Bereinigen Sie, indem Sie den
subtree-split-result
Zweig löschengit branch -D subtree-split-result
Entfernen Sie die Fernbedienung, die Sie hinzugefügt haben, um die Daten aus dem Quell-Repo abzurufen
git remote rm merge-source-repo
quelle
Eine weitere Antwort hinzufügen, da ich denke, dass dies etwas einfacher ist. Ein Pull von repo_dest wird in repo_to_import ausgeführt und dann ein Push --set-upstream url: repo_dest master wird ausgeführt.
Diese Methode hat bei mir funktioniert, indem ich mehrere kleinere Repos in ein größeres importiert habe.
So importieren Sie: repo1_to_import to repo_dest
Benennen oder verschieben Sie Dateien und Verzeichnisse an die gewünschte Position im ursprünglichen Repo, bevor Sie den Import durchführen. z.B
Die unter dem folgenden Link beschriebene Methode hat diese Antwort inspiriert. Ich mochte es, weil es einfacher schien. Aber Vorsicht! Es gibt Drachen! https://help.github.com/articles/importing-an-external-git-repository verschiebt
git push --mirror url:repo_dest
Ihren lokalen Repo-Verlauf und -Status auf remote (URL: repo_dest). ABER es löscht die alte Geschichte und den Zustand der Fernbedienung. Spaß folgt! : -Equelle
Ich wollte in meinem Fall nur einige Dateien aus dem anderen Repository (XXX) importieren. Der Teilbaum war zu kompliziert für mich und die anderen Lösungen funktionierten nicht. Das habe ich getan:
Auf diese Weise erhalten Sie eine durch Leerzeichen getrennte Liste aller Commits, die sich auf die Dateien auswirken, die ich importieren wollte (ZZZ), und zwar in umgekehrter Reihenfolge (möglicherweise müssen Sie --follow hinzufügen, um auch Umbenennungen zu erfassen). Ich ging dann in das Ziel-Repository (JJJ), fügte das andere Repository (XXX) als Remote hinzu, holte es ab und schließlich:
Wenn Sie alle Commits zu Ihrem Zweig hinzufügen, haben Sie alle Dateien mit ihrem Verlauf und können mit ihnen alles tun, was Sie wollen, als wären sie schon immer in diesem Repository.
quelle
Siehe Basisbeispiel in diesem Artikel und berücksichtigen Sie eine solche Zuordnung für Repositorys:
A
<->YYY
,B
<->XXX
Entfernen Sie nach allen in diesem Kapitel beschriebenen Aktivitäten (nach dem Zusammenführen) den Zweig
B-master
:Drücken Sie dann die Änderungen.
Für mich geht das.
quelle
Ich war in einer Situation, in der ich gesucht habe,
-s theirs
aber diese Strategie gibt es natürlich nicht. Meine Geschichte war, dass ich ein Projekt auf GitHub gegabelt hatte und jetzt aus irgendeinem Grund mein lokalesmaster
nicht mit zusammengeführt werden konnteupstream/master
obwohl ich keine lokalen Änderungen an diesem Zweig vorgenommen hatte. (Ich weiß wirklich nicht, was dort passiert ist - ich glaube, Upstream hat hinter den Kulissen vielleicht ein paar schmutzige Stöße gemacht?)Was ich am Ende tat, war
Jetzt ist my
master
wieder synchron mitupstream/master
(und Sie können das oben Gesagte für jeden anderen Zweig wiederholen, den Sie ebenfalls ähnlich synchronisieren möchten).quelle
git reset --hard upstream/master
Mitarbeiter in Ihrermaster
Zweigstelle würde den Job erledigen. Auf diese Weise verlieren Sie nicht den lokalen Zweigkonflikt - Dinge wie den Standard-Upstream.Ich kann eine andere Lösung (Alternative zu Git-Submodulen ) für Ihr Problem vorschlagen - das Gil-Tool (Git-Links)
Es ermöglicht die Beschreibung und Verwaltung komplexer Abhängigkeiten von Git-Repositorys.
Außerdem bietet es eine Lösung für das Abhängigkeitsproblem der rekursiven Git-Submodule .
Angenommen, Sie haben die folgenden Projektabhängigkeiten: Beispiel eines Git-Repository-Abhängigkeitsdiagramms
Anschließend können Sie eine
.gitlinks
Datei mit einer Beschreibung der Repositorys definieren:Jede Zeile beschreibt Git Link im folgenden Format:
Schließlich müssen Sie Ihr Root-Beispiel-Repository aktualisieren:
Als Ergebnis klonen Sie alle erforderlichen Projekte und verknüpfen sie ordnungsgemäß miteinander.
Wenn Sie alle Änderungen in einem Repository mit allen Änderungen in untergeordneten verknüpften Repositorys festschreiben möchten, können Sie dies mit einem einzigen Befehl tun:
Pull, Push-Befehle funktionieren auf ähnliche Weise:
Das Gil-Tool (Git-Links) unterstützt die folgenden Befehle:
Weitere Informationen zum Abhängigkeitsproblem von rekursiven Git-Submodulen .
quelle
Lassen Sie mich Namen
a
(anstelle vonXXX
undZZZ
) undb
(anstelle vonYYY
) verwenden, da dadurch die Beschreibung etwas leichter zu lesen ist.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
Ich kenne keinen einfachen Weg, das zu tun. Sie könnten dies tun:
Ich kann mit Details bearbeiten, wenn das ansprechend klingt.
quelle
Ich denke, Sie können dies mit 'git mv' und 'git pull' tun.
Ich bin ein fairer Idiot - seien Sie also vorsichtig mit Ihrem Haupt-Repository -, aber ich habe es nur in einem temporären Verzeichnis versucht und es scheint zu funktionieren.
Benennen Sie zuerst die Struktur von XXX so um, dass sie dem Aussehen entspricht, wenn sie sich in JJJ befindet:
Jetzt sieht XXX so aus:
Verwenden Sie nun 'git pull', um die Änderungen abzurufen:
Jetzt sieht JJJ so aus:
quelle