Wie führt man zwei Git-Repositories zusammen?

Lesezeit: 11 Minuten

Wie fuhrt man zwei Git Repositories zusammen
static_rtti

Betrachten Sie das folgende Szenario:

Ich habe ein kleines experimentelles Projekt A in einem eigenen Git-Repo entwickelt. Es ist jetzt ausgereift, und ich möchte, dass A Teil des größeren Projekts B ist, das sein eigenes großes Repository hat. Ich möchte jetzt A als Unterverzeichnis von B hinzufügen.

Wie verschmelze ich A mit B, ohne die Geschichte auf irgendeiner Seite zu verlieren?

  • Wenn Sie nur versuchen, zwei Repositorys zu einem zu kombinieren, ohne beide Repositorys behalten zu müssen, werfen Sie einen Blick auf diese Frage: stackoverflow.com/questions/13040958/…

    – Flimmer

    6. Januar 2014 um 16:06 Uhr

  • Verwenden Sie zum Zusammenführen von Git-Repo in einem benutzerdefinierten Verzeichnis mit Speichern aller Comits stackoverflow.com/a/43340714/1772410

    – Andrej Izman

    11. April 2017 um 11:14 Uhr


Wie fuhrt man zwei Git Repositories zusammen
Andresch Serj

Wenn Sie zusammenführen möchten project-a hinein project-b:

cd path/to/project-b
git remote add project-a /path/to/project-a
git fetch project-a --tags
git merge --allow-unrelated-histories project-a/master # or whichever branch you want to merge
git remote remove project-a

Entnommen aus: git verschiedene Repositories zusammenführen?

Diese Methode hat bei mir ziemlich gut funktioniert, sie ist kürzer und meiner Meinung nach viel sauberer.

Falls Sie setzen möchten project-a in ein Unterverzeichnis, können Sie verwenden git-filter-repo (filter-branch ist entmutigt). Führen Sie die folgenden Befehle vor den obigen Befehlen aus:

cd path/to/project-a
git filter-repo --to-subdirectory-filter project-a

Ein Beispiel für das Zusammenführen von 2 großen Repositories, wobei eines davon in ein Unterverzeichnis gelegt wird: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731

Notiz: Die --allow-unrelated-histories parameter existiert erst seit git >= 2.9. Sehen Git – git merge Dokumentation / –allow-unrelated-histories

Aktualisieren: Hinzugefügt --tags wie von @jstadler vorgeschlagen, um Tags beizubehalten.

  • Das hat das Geschäft für mich erledigt. Hat beim ersten Mal wie ein Zauber funktioniert, mit nur einem Konflikt in der .gitignore-Datei! Es hat die Commit-Historie perfekt bewahrt. Das große Plus gegenüber anderen Ansätzen – neben der Einfachheit – ist, dass hierdurch kein fortlaufender Verweis auf das Merged Repo erfolgen muss. Eine Sache, auf die Sie jedoch achten sollten – wenn Sie ein iOS-Entwickler wie ich sind – ist, sehr vorsichtig zu sein, wenn Sie die Projektdatei des Ziel-Repositorys in den Arbeitsbereich einfügen.

    – Max MacLeod

    26. Juni 2015 um 8:31 Uhr

  • Danke. Hat für mich funktioniert. Ich musste das zusammengeführte Verzeichnis in einen Unterordner verschieben, also nachdem ich die obigen Schritte ausgeführt hatte, benutzte ich einfach git mv source-dir/ dest/new-source-dir

    – Sid

    1. Februar 2016 um 20:33 Uhr


  • @sg Ein indirekter Weg wäre, alle diese Dateien in project-a in ein Unterverzeichnis in project-a zu verschieben (so dass die oberste Ebene von project-a nur dieses eine Verzeichnis hat) und dann dem obigen Prozess zu folgen.

    – Sid

    4. April 2016 um 12:51 Uhr

  • Die git merge Schritt scheitert hier mit fatal: refusing to merge unrelated histories; --allow-unrelated-histories behebt das wie in der erklärt Dokumente.

    – ssc

    22. Juli 2016 um 13:14 Uhr


  • Kürzer: git fetch /path/to/project-a master; git merge --allow-unrelated-histories FETCH_HEAD.

    – jthill

    9. Januar 2017 um 16:49 Uhr

Hier sind zwei mögliche Lösungen:

Submodule

Entweder Repository A in ein separates Verzeichnis im größeren Projekt B kopieren oder (vielleicht besser) Repository A in ein Unterverzeichnis in Projekt B klonen. Dann verwenden git-Submodul um dieses Repository zu erstellen a Submodul eines Depots B.

Dies ist eine gute Lösung für lose gekoppelte Repositorys, bei denen die Entwicklung in Repository A fortgesetzt wird und der Hauptteil der Entwicklung eine separate eigenständige Entwicklung in A ist. Siehe auch SubmoduleSupport und GitSubmoduleTutorial Seiten im Git-Wiki.

Teilbaum zusammenführen

Sie können Repository A mit einem Unterverzeichnis von Projekt B zusammenführen Teilbaum zusammenführen Strategie. Dies ist beschrieben in Teilbaumverschmelzung und Sie von Markus Prinz.

git remote add -f Bproject /path/to/B
git merge -s ours --allow-unrelated-histories --no-commit Bproject/master
git read-tree --prefix=dir-B/ -u Bproject/master
git commit -m "Merge B project as our subdirectory"
git pull -s subtree Bproject master

(Möglichkeit --allow-unrelated-histories wird für Git >= 2.9.0 benötigt.)

Oder Sie können verwenden git-Teilbaum Werkzeug (Repository auf GitHub) von apenwarr (Avery Pennarun), angekündigt beispielsweise in seinem Blogbeitrag Eine neue Alternative zu Git-Submodulen: git subtree.


Ich denke, in Ihrem Fall (A soll Teil eines größeren Projekts B sein) wäre die richtige Lösung zu verwenden Teilbaum zusammenführen.

  • Dies funktioniert und scheint den Verlauf beizubehalten, aber nicht so, dass Sie ihn zum Vergleichen von Dateien oder zum Halbieren der Zusammenführung verwenden könnten. Übersehe ich einen Schritt?

    – jettero

    7. Mai 2012 um 12:44 Uhr

  • das ist unvollständig. Ja, Sie erhalten eine Menge Commits, aber sie verweisen nicht mehr auf die richtigen Pfade. git log dir-B/somefile zeigt nichts außer der einen Zusammenführung. Siehe Greg Hewgills Antwort bezieht sich auf dieses wichtige Thema.

    – Kunstvoller Roboter

    1. Juni 2012 um 14:52 Uhr

  • WICHTIG: git pull –no-rebase -s subtree Bproject master Wenn Sie dies nicht tun und Pull auf automatisches Rebase eingestellt haben, erhalten Sie am Ende “Objekt konnte nicht analysiert werden”. Sehen osdir.com/ml/git/2009-07/msg01576.html

    – Eric Bowman – Abstrakt –

    16. September 2012 um 14:35 Uhr


  • Diese Antwort kann verwirrend sein, da sie B als zusammengeführten Teilbaum hat, obwohl es in der Frage A war. Ergebnis eines Kopierens und Einfügens?

    – vfclists

    20. September 2012 um 11:32 Uhr


  • Wenn Sie versuchen, zwei Repositorys einfach zusammenzukleben, sind Submodule und Subtree-Merges das falsche Werkzeug, da sie nicht den gesamten Dateiverlauf beibehalten (wie andere Kommentatoren angemerkt haben). Siehe stackoverflow.com/questions/13040958/….

    – Eric Lee

    23. Januar 2013 um 0:06 Uhr

1646905094 815 Wie fuhrt man zwei Git Repositories zusammen
Simon Perepeliza

Ein einzelner Zweig eines anderen Repositorys kann einfach unter einem Unterverzeichnis platziert werden, das seinen Verlauf beibehält. Zum Beispiel:

git subtree add --prefix=rails git://github.com/rails/rails.git master

Dies wird als einzelnes Commit angezeigt, bei dem alle Dateien des Rails-Master-Zweigs zum Verzeichnis „rails“ hinzugefügt werden. Der Titel des Commits enthält jedoch einen Verweis auf den alten Verlaufsbaum:

Füge „rails/“ aus Commit hinzu <rev>

Woher <rev> ist ein SHA-1-Commit-Hash. Sie können immer noch die Geschichte sehen, einige Änderungen verantwortlich machen.

git log <rev>
git blame <rev> -- README.md

Beachten Sie, dass Sie das Verzeichnispräfix von hier aus nicht sehen können, da dies ein tatsächlicher alter Zweig ist, der intakt geblieben ist. Sie sollten dies wie einen gewöhnlichen Dateiverschiebungs-Commit behandeln: Sie benötigen einen zusätzlichen Sprung, wenn Sie ihn erreichen.

# finishes with all files added at once commit
git log rails/README.md

# then continue from original tree
git log <rev> -- README.md

Es gibt komplexere Lösungen, wie dies manuell zu tun oder den Verlauf wie in anderen Antworten beschrieben neu zu schreiben.

Der Befehl git-subtree ist Teil des offiziellen git-contrib, einige Paketmanager installieren ihn standardmäßig (OS X Homebrew). Aber Sie müssen es möglicherweise zusätzlich zu Git selbst installieren.

  • Hier sind Anweisungen zur Installation von Git SubTree (Stand Juni 2013): stackoverflow.com/a/11613541/694469 (und ich habe ersetzt git co v1.7.11.3 mit ... v1.8.3).

    – KajMagnus

    7. Juni 2013 um 14:31 Uhr

  • Vielen Dank für die Hinweise zu der folgenden Antwort. Ab Git 1.8.4 ist ‘subtree’ immer noch nicht enthalten (zumindest nicht auf Ubuntu 12.04 git ppa (ppa:git-core/ppa) )

    – Matt Klein

    30. September 2013 um 2:10 Uhr

  • Das kann ich danach bestätigen, git log rails/somefile wird den Commit-Verlauf dieser Datei außer dem Merge-Commit nicht anzeigen. Überprüfen Sie, wie @artfulrobot vorgeschlagen hat, die Antwort von Greg Hewgill. Und Sie müssen möglicherweise verwenden git filter-branch auf dem Repo, das Sie einschließen möchten.

    – Jifeng Zhang

    8. Oktober 2013 um 12:07 Uhr

  • Oder lesen Sie Eric Lees „Merging Two Git Repositories Into One Repository Without Losing File History“ saintgimp.org/2013/01/22/…

    – Jifeng Zhang

    8. Oktober 2013 um 12:17 Uhr


  • Wie andere gesagt haben, git subtree kann nicht tun, was Sie denken! Sehen Sie hier für eine vollständigere Lösung.

    – Paul Tucher

    1. Februar 2014 um 8:13 Uhr

Der Submodul-Ansatz ist gut, wenn Sie das Projekt separat pflegen möchten. Wenn Sie jedoch wirklich beide Projekte in dasselbe Repository zusammenführen möchten, haben Sie etwas mehr Arbeit vor sich.

Das erste wäre, zu verwenden git filter-branch um die Namen von allem im zweiten Repository so umzuschreiben, dass es sich in dem Unterverzeichnis befindet, in dem sie enden sollen. Also statt foo.c, bar.htmldu würdest haben projb/foo.c und projb/bar.html.

Dann sollten Sie in der Lage sein, Folgendes zu tun:

git remote add projb [wherever]
git pull projb

Die git pull wird ein tun git fetch gefolgt von einem git merge. Es sollte keine Konflikte geben, wenn das Repository, zu dem Sie ziehen, noch keine hat projb/ Verzeichnis.

Weitere Suche deutet darauf hin, dass etwas Ähnliches getan wurde, um zusammenzuführen gitk hinein git. Junio ​​C Hamano schreibt hier darüber: http://www.mail-archive.com/git@vger.kernel.org/msg03395.html

Wie fuhrt man zwei Git Repositories zusammen
Paul Tucher

git-subtree ist nett, aber es ist wahrscheinlich nicht das, was Sie wollen.

Zum Beispiel, wenn projectA ist das in B erstellte Verzeichnis, nach git subtree,

git log projectA

Listen nur eine Commit: die Zusammenführung. Die Commits aus dem zusammengeführten Projekt gelten für unterschiedliche Pfade, sodass sie nicht angezeigt werden.

Die Antwort von Greg Hewgill kommt dem am nächsten, obwohl sie nicht wirklich sagt, wie die Pfade umgeschrieben werden sollen.


Die Lösung ist überraschend einfach.

(1) In A,

PREFIX=projectA #adjust this

git filter-branch --index-filter '
    git ls-files -s |
    sed "s,\t,&'"$PREFIX"'/," |
    GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
    mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD

Hinweis: Dies schreibt den Verlauf um; Vielleicht möchten Sie zuerst eine Sicherungskopie von A erstellen.

Hinweis Bene: Sie müssen das Ersatzskript innerhalb des sed-Befehls ändern, falls Sie Nicht-ASCII-Zeichen (oder weiße Zeichen) in Dateinamen oder Pfaden verwenden. In diesem Fall beginnt der Dateispeicherort innerhalb eines von “ls-files -s” erzeugten Datensatzes mit einem Anführungszeichen.

(2) Dann in B laufen

git pull path/to/A

Voila! Du hast ein projectA Verzeichnis in B. Wenn Sie ausführen git log projectAsehen Sie alle Commits von A.


In meinem Fall wollte ich zwei Unterverzeichnisse, projectA und projectB. In diesem Fall habe ich auch Schritt (1) bis B gemacht.

  • Anscheinend haben Sie Ihre Antwort von stackoverflow.com/a/618113/586086 kopiert?

    – Andreas Mao

    1. April 2014 um 21:47 Uhr

  • @AndrewMao, ich denke schon … ich kann mich eigentlich nicht erinnern. Ich habe dieses Skript ziemlich oft verwendet.

    – Paul Tucher

    1. April 2014 um 22:38 Uhr

  • Ich würde hinzufügen, dass \t unter OS X nicht funktioniert und Sie eingeben müssen

    – Muneeb Ali

    24. Dezember 2014 um 21:56 Uhr

  • "$GIT_INDEX_FILE" muss (zweimal) in Anführungszeichen gesetzt werden, sonst schlägt Ihre Methode fehl, wenn zB der Pfad Leerzeichen enthält.

    – Rob W

    17. Januar 2015 um 14:43 Uhr

  • Wenn Sie sich fragen, um ein in osx einzufügen, müssen Sie dies tun Ctrl-V <tab>

    – Casey

    19. Juli 2015 um 9:51 Uhr

Wenn beide Repositorys dieselbe Art von Dateien haben (wie zwei Rails-Repositorys für verschiedene Projekte), können Sie Daten des sekundären Repositorys in Ihr aktuelles Repository holen:

git fetch git://repository.url/repo.git master:branch_name

und führen Sie es dann mit dem aktuellen Repository zusammen:

git merge --allow-unrelated-histories branch_name

Wenn Ihre Git-Version kleiner als 2.9 ist, entfernen Sie sie --allow-unrelated-histories.

Danach können Konflikte auftreten. Sie können sie zum Beispiel mit lösen git mergetool. kdiff3 kann nur mit Tastatur verwendet werden, so dass 5 Konfliktdatei beim Lesen des Codes nur wenige Minuten dauert.

Denken Sie daran, die Zusammenführung abzuschließen:

git commit

  • Anscheinend haben Sie Ihre Antwort von stackoverflow.com/a/618113/586086 kopiert?

    – Andreas Mao

    1. April 2014 um 21:47 Uhr

  • @AndrewMao, ich denke schon … ich kann mich eigentlich nicht erinnern. Ich habe dieses Skript ziemlich oft verwendet.

    – Paul Tucher

    1. April 2014 um 22:38 Uhr

  • Ich würde hinzufügen, dass \t unter OS X nicht funktioniert und Sie eingeben müssen

    – Muneeb Ali

    24. Dezember 2014 um 21:56 Uhr

  • "$GIT_INDEX_FILE" muss (zweimal) in Anführungszeichen gesetzt werden, sonst schlägt Ihre Methode fehl, wenn zB der Pfad Leerzeichen enthält.

    – Rob W

    17. Januar 2015 um 14:43 Uhr

  • Wenn Sie sich fragen, um ein in osx einzufügen, müssen Sie dies tun Ctrl-V <tab>

    – Casey

    19. Juli 2015 um 9:51 Uhr

1646905096 404 Wie fuhrt man zwei Git Repositories zusammen
Calahad

Ich habe bei der Verwendung von Merge immer wieder den Verlauf verloren, also habe ich Rebase verwendet, da in meinem Fall die beiden Repositories so unterschiedlich sind, dass sie nicht bei jedem Commit zusammengeführt werden:

git clone git@gitorious/projA.git projA
git clone git@gitorious/projB.git projB

cd projB
git remote add projA ../projA/
git fetch projA 
git rebase projA/master HEAD

=> Konflikte lösen, dann weitermachen, so oft wie nötig…

git rebase --continue

Dies führt dazu, dass ein Projekt alle Commits von projA enthält, gefolgt von Commits von projB

987370cookie-checkWie führt man zwei Git-Repositories zusammen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy