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 subtreezu 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:
git subtree add --prefix .vim/bundle/example https://github.com/Example/vim-example.git master --squashDadurch 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:
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: b999b09cd9d69f359fa5668e81b09dcfde455ccaUm das Unterverzeichnis auf die neueste Version des Child-Repository zu aktualisieren, führen Sie Folgendes aus:
git subtree pull --prefix .vim/bundle/example https://github.com/Example/vim-example.git master --squashgit 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:
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, --quiet | Unterdrückt unnötige Ergebnisnachrichten auf stderr. |
|---|---|
| -d, --debug | Gibt 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:
git subtree add --prefix .vim/bundle/vim-double-upon https://hostname.org/example/vim-plugins.git master --squashDer 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:
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:
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:
git subtree pull --prefix .vim/bundle/vim-double-upon https://hostname.org/example/vim-plugins.git master --squashUm Änderungen zurück an das Upstream-Repository beizutragen, extrahieren Sie die Subtree-Historie mit git subtree split:
git subtree split --prefix .vim/bundle/vim-double-upon -b split-branch
git push split-branchDadurch 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:
git remote add -f vim-double-upon https://hostname.org/example/vim-plugins.gitFügen Sie den Subtree hinzu:
git subtree add --prefix .vim/bundle/vim-double-upon vim-double-upon master --squashAktualisieren Sie das Unterprojekt so:
git fetch vim-double-upon master
git subtree pull --prefix .vim/bundle/vim-double-upon vim-double-upon master --squashGit 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?