Zum Inhalt springen

Git Subtree

Wie bereits auf unserer vorherigen Seite erwähnt, ist Git Submodule für bestimmte Fälle nützlich. Für das Nachverfolgen von Softwareabhängigkeiten bevorzugen viele Entwickler Git Subtree.

Was ist Git Subtree

Git Subtree ist eine Alternative zu Git Submodule. Es ermöglicht, ein Repository als Unterverzeichnis in ein anderes einzubetten. Es ist eine der Möglichkeiten, die Historie von Softwareabhängigkeiten nachzuverfolgen. Subtrees sollten jedoch nicht mit Submodulen verwechselt werden. Im Gegensatz zu Submodulen benötigen Subtrees keine .gitmodules-Dateien oder Gitlinks im Repository. Ein Subtree ist einfach ein Unterverzeichnis, in das Sie zusammen mit Ihrem Projekt committen, verzweigen und mergen können.

Warum Git Subtree verwenden

Vorteile

  • Unterstützt ab Git 1.7.10 und höher.
  • Einfache Verwaltung des Workflows.
  • Verfügbarer Code des Unterprojekts, nachdem das Superprojekt fertig ist.
  • Keine neuen Git-Kenntnisse erforderlich, um git subtree zu verwenden.
  • Fügt keine neuen Metadatendateien hinzu (z. B. .gitmodules).
  • Ermöglicht Änderungen am Inhalt ohne separate Repository-Kopie der Abhängigkeit.

Nachteile

  • Erfordert das Erlernen einer neuen Merge-Strategie.
  • Komplizierter Prozess, um Code zurück an die Upstream-Unterprojekte beizutragen.
  • Code von Super- und Unterprojekt ist im selben Repository vermischt.

Wie man Git Subtrees verwendet

Nehmen wir an, es gibt ein externes Projekt, das Sie zu Ihrem Repository hinzufügen möchten.

Um beispielsweise eine Vim-Erweiterung in ein Repository hinzuzufügen, das Ihre Vim-Einrichtung speichert, gehen Sie wie folgt vor:

bash
git subtree add --prefix .vim/bundle/example https://github.com/Example/vim-example.git master --squash

Dadurch wird die gesamte Historie des Projekts vim-example in Ihren Ordner .vim/bundle/example zusammengeführt und die SHA-1 von master zum Zeitpunkt der Aktion für spätere Referenz gespeichert. Die Ausgabe sieht wie folgt aus und enthält zwei Commits:

bash
commit 6d7054b3acea64e2e31f4d6fb2e3be12e5865e87
Merge: 87fa91e ef86deb
Author: Ann Smith<[email protected]m>
Date:   Tue Jun 10 13:37:03 2016 +0200
    Merge commit 'fe67ddf158faccff4082d78a25c45d8cd93e8ba8' as '.vim/bundle/example'
commit fe67ddf158faccff4082d78a25c45d8cd93e8ba8
Author: Ann Smith<[email protected]m>
Date:   Tue May 12 13:37:03 2015 +0200
    Squashed '.vim/bundle/example/' content from commit b999b09
    git-subtree-dir: .vim/bundle/example
    git-subtree-split: b999b09cd9d69f359fa5668e81b09dcfde455cca

Um das Unterverzeichnis auf die neueste Version des Child-Repository zu aktualisieren, führen Sie Folgendes aus:

bash
git subtree pull --prefix .vim/bundle/example https://github.com/Example/vim-example.git master --squash

git subtree speichert jedoch Commit-IDs von Unterprojekten und keine Verweise in den Metadaten. Finden Sie den symbolischen Namen, der mit einem Commit verknüpft ist:

bash
git ls-remote https://github.com/Example/vim-example.git | grep <commit-sha>

Ersetzen Sie <commit-sha> durch den tatsächlichen Commit-Hash.

Rebase nach Git Subtree

Um ein Repository mit Subtrees per Rebase neu aufzusetzen, verwenden Sie den Modus --interactive von git rebase. Sie können die Merge-Commits des Subtrees entfernen oder zusammenfassen und anschließend git rebase --continue ausführen. Beachten Sie, dass das Umschreiben der Historie danach ein erneutes Ausführen von git subtree add oder git subtree pull erfordert. Seien Sie sich bewusst, dass das Umschreiben der Historie beim Rebasen von Subtrees Merge-Konflikte verursachen kann, da sich die Commit-Struktur ändert.

OPTIONEN

-q, --quietUnterdrückt unnötige Ergebnisnachrichten auf stderr.
-d, --debugGibt zusätzliche Debug-Nachrichten auf stderr aus.
-P <prefix>, --prefix=<prefix>Definiert den Pfad im Repository zu dem Subtree, den Sie bearbeiten möchten. Dies ist für alle Befehle obligatorisch.
-m <message>, --message=<message>Gibt <message> als Commit-Nachricht für den Merge-Commit an. Dies ist nur für add, merge und pull gültig.

Git Subtree ohne Remote-Tracking verwenden

Fügen Sie das Git-Subtree in einem angegebenen Präfix-Ordner hinzu. Verwenden Sie das Flag --squash, um die gesamte Historie des Unterprojekts in Ihrem Haupt-Repository zu bewahren:

bash
git subtree add --prefix .vim/bundle/vim-double-upon https://hostname.org/example/vim-plugins.git master --squash

Der Befehl führt einen Fetch aus und fasst die Historie zusammen. Die Ausgabe zeigt typischerweise den Fortschritt des Fetchs, gefolgt von der Bestätigung des Hinzufügens:

bash
git fetch https://hostname.org/example/vim-plugins.git  master
warning: no common commits
remote: Counting objects: 325, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 325 (delta 101), reused 313 (delta 89)
Receiving objects: 100% (325/325), 61.47 KiB, done.
Resolving deltas: 100% (110/110), done.
From https://hostname.org/vim-plugins.git
* branch master -> FETCH_HEAD
Added dir '.vim/bundle/vim-double-upon'

Dadurch wird ein Merge-Commit erstellt, indem die gesamte Historie des Unterprojekts zu einem einzigen Commit zusammengeführt wird:

bash
3bca0ad [4 minutes ago] (HEAD, stree) Merge commit 'fa2f5dc4f1b94356bca8a440c786a94f75dc0a45' as '.vim/bundle/vim-double-upon' [John Brown]
fa2f5dc [4 minutes ago] Squashed '.vim/bundle/vim-double-upon/' content from commit 13189ec [John Brown]

Um den Code des Plugins aus dem Upstream-Repository zu aktualisieren, führen Sie git subtree pull aus:

bash
git subtree pull --prefix .vim/bundle/vim-double-upon https://hostname.org/example/vim-plugins.git master --squash

Um Änderungen zurück an das Upstream-Repository beizutragen, extrahieren Sie die Subtree-Historie mit git subtree split:

bash
git subtree split --prefix .vim/bundle/vim-double-upon -b split-branch
git push split-branch

Dadurch wird ein neuer Branch erstellt, der nur die Historie des Subtrees enthält und anschließend an das Upstream-Repository gepusht werden kann.

Um die Befehle zu verkürzen, fügen Sie das Unterprojekt als Remote hinzu.

Unterprojekt als Remote hinzufügen

Das Hinzufügen als Remote verkürzt den Prozess:

bash
git remote add -f vim-double-upon https://hostname.org/example/vim-plugins.git

Fügen Sie den Subtree hinzu:

bash
git subtree add --prefix .vim/bundle/vim-double-upon vim-double-upon master --squash

Aktualisieren Sie das Unterprojekt so:

bash
git fetch vim-double-upon master
git subtree pull --prefix .vim/bundle/vim-double-upon vim-double-upon master --squash

Git Subtree ist eine Alternative zu Submodulen. Während Submodule ein anderes Projekt in ein Verzeichnis einfügen und das Remote-Repository synchron halten, behält Git Subtree das Unterprojekt als normales Verzeichnis bei. Um Änderungen zurück an das Upstream-Repository beizutragen, muss git subtree split verwendet werden, um die Historie des Unterprojekts zu extrahieren, da eine direkte bidirektionale Synchronisierung nicht nativ unterstützt wird.

Practice

What are the features and usage of Git subtree?

Finden Sie das nützlich?

Dual-run-Vorschau — vergleichen Sie mit den Symfony-Routen live.