Git subtree: die Alternative zum Git-Submodul
NICOLA PAOLUCCI
Developer Advocate
Im Internet finden sich unzählige Artikel dazu, warum du keine Git-Submodule verwenden solltest. Submodule sind zwar für einige Anwendungsfälle nützlich, haben aber mehrere Nachteile.
Gibt es Alternativen? Allerdings! Zwei (wenn nicht mehr) Tools helfen dir, den Verlauf von Software-Abhängigkeiten in deinem Projekt nachzuverfolgen, während du deine Arbeit mit Git fortsetzt:
git subtree
- Google Repo
In diesem Blogpost werfen wir einen Blick auf git subtree
und erklären, warum es zwar nicht perfekt, aber immerhin viel besser als git submodule ist.
Was ist git subtree und warum sollte ich es nutzen?
Mit git subtree
kannst du ein Repository als Unterverzeichnis in einem anderen verschachteln. Dies ist eine von mehreren Möglichkeiten, wie Git-Projekte Projektabhängigkeiten verwalten können.
Warum du vielleicht git subtree
in Betracht ziehen solltest:
- Das Management eines einfachen Workflows ist kinderleicht.
- Ältere Git-Versionen werden unterstützt (sogar Versionen vor 1.5.2).
- Der Code des Unterprojekts steht bereit, sobald der Klon des Superprojekts erstellt worden ist.
- Mit
git subtree
müssen Benutzer deines Repositorys nichts Neues dazulernen. Sie können Abhängigkeiten verwalten, ohne überhaupt zu wissen, dass dugit subtree
verwendest. - Mit
git subtree
werden anders als bei Git-Submodulen (d. h. .gitmodule) keine neuen Dateien mit Metadaten hinzugefügt. - Inhalte des Moduls können bearbeitet werden, ohne dass eine separate Repository-Kopie der Abhängigkeit an einem anderen Ort benötigt wird.
Nachteile (aber unserer Meinung nach sind sie weitgehend akzeptabel):
- Du musst eine neue Merge-Strategie lernen (nämlich
git subtree
). - Codebeiträge zum Upstream für Unterprojekte sind ein bisschen komplizierter.
- Die Verantwortung, Code von über- und untergeordneten Projekten in Commits nicht zu vermischen, liegt bei dir.
Zugehöriges Material
Verschieben eines vollständigen Git-Repositorys
Lösung anzeigen
Git kennenlernen mit Bitbucket Cloud
Wie wird git subtree verwendet?
git subtree
ist in verfügbaren Git-Versionen ab 1.7.11 seit Mai 2012 integriert. Subtree wird in der von Homebrew installierten Version auf OS X bereits richtig eingepasst. Bei einigen anderen Plattformen musst du die Installationsanweisungen beachten.
Hier ist ein klassisches Beispiel für die Nachverfolgung eines Vim-Plug-ins mit git subtree
.
Die schnelle Lösung ohne Remote-Verfolgung
Wenn du nur ein paar Einzeiler zum Kopieren und Einfügen brauchst, lies einfach diesen Abschnitt. Füge git subtree
zu einem bestimmten prefix-Ordner hinzu:
git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash
(Üblicherweise speichert man nicht den gesamten Verlauf des Unterprojekts im Haupt-Repository (main). Wenn du das aber tun willst, musst du nur den Flag --squash auslassen.)
Der obige Befehl führt zu dieser Ausgabe:
git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git main
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 338 (delta 101), reused 323 (delta 89)
Receiving objects: 100% (338/338), 71.46 KiB, done.
Resolving deltas: 100% (101/101), done.
From https://bitbucket.org/vim-plugins-mirror/vim-surround.git
* branch main -} FETCH_HEAD
Added dir '.vim/bundle/tpope-vim-surround'
Wie du siehst, wird hier ein Merge-Commit dokumentiert, wobei der gesamte Verlauf des vim-surround-Repositorys in einen einzigen Commit gesquasht wird:
1bda0bd [3 minutes ago] (HEAD, stree) Merge commit 'ca1f4da9f0b93346bba9a430c889a95f75dc0a83' as '.vim/bundle/tpope-vim-surround' [Nicola Paolucci]
ca1f4da [3 minutes ago] Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea [Nicola Paolucci]
Wenn du den Plug-in-Code später vom Upstream-Repository aktualisieren willst, geht das nur mit einem git subtree
-Pull:
git subtree pull --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash
Dies ist sehr kurz und schmerzlos, aber die Befehle sind relativ lang und schwer zu merken. Wir können die Befehle verkürzen, indem wir das Unterprojekt als Remote hinzufügen.
Hinzufügen des Unterprojekts als Remote
Wenn wir den Unterbaum als Remote hinzufügen, können wir in verkürzter Form auf ihn verweisen:
git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git
Jetzt können wir den Unterbaum (wie vorhin auch) hinzufügen, aber wir verweisen auf den Remote in Kurzform.
git subtree add --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash
Der Befehl zur Aktualisierung des Unterprojekts zu einem späteren Zeitpunkt lautet dann folgendermaßen:
git fetch tpope-vim-surround main
git subtree pull --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash
Beitragen zum Upstream
Wir können nun uneingeschränkt unsere Korrekturen an das Unterprojekt in unserem lokalen Arbeitsverzeichnis committen. Wenn dein Code soweit ist, zurück in das Upstream-Projekt gepusht zu werden, müssen wir das Projekt zunächst abspalten und dann als weiteren Remote hinzufügen:
git remote add durdn-vim-surround ssh://git@bitbucket.org/durdn/vim-surround.git
Jetzt können wir den Befehl subtree push wie hier ausführen:
git subtree push --prefix=.vim/bundle/tpope-vim-surround/ durdn-vim-surround main
git push using: durdn-vim-surround main
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To ssh://git@bitbucket.org/durdn/vim-surround.git
02199ea..dcacd4b dcacd4b21fe51c9b5824370b3b224c440b3470cb -} main
Anschließend können wir eine Pull-Anfrage an den Maintainer des Pakets senden.
Kann ich das tun, ohne den git subtree-Befehl zu verwenden?
Ja, das kannst du! git subtree
gehört nicht zur Subtree-Merge-Strategie. Du kannst die Merge-Strategie auch dann anwenden, wenn git subtree
aus irgendeinem Grund nicht verfügbar ist. So gehst du dabei vor:
Füge die Abhängigkeit einfach mit git remote
hinzu:
git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git
Bevor die Inhalte der Abhängigkeit in das Repository eingelesen werden, muss der Merge unbedingt dokumentiert werden, damit wir den gesamten Baumverlauf des Plug-ins bis zu diesem Punkt verfolgen können:
git merge -s ours --no-commit tpope-vim-surround/main
Die daraus resultierende Ausgabe lautet:
Automatic merge went well; stopped before committing as requested
Daraufhin lesen wir den Inhalt des neuesten Baumobjekts in das Plug-in-Repository in unserem Arbeitsverzeichnis ein, das bereit für einen Commit ist:
git read-tree --prefix=.vim/bundle/tpope-vim-surround/ -u tpope-vim-surround/main
Jetzt können wir den Commit durchführen (dabei handelt es sich um einen Merge-Commit, bei dem der Verlauf des eingelesenen Baums erhalten bleibt).
git ci -m"[subtree] adding tpope-vim-surround"
[stree 779b094] [subtree] adding tpope-vim-surround
Zum Aktualisieren des Projekts können wir nun einen Pull unter Verwendung der git subtree
-Merge-Strategie durchführen:
git pull -s subtree tpope-vim-surround main
git subtree ist eine großartige Alternative
Wenn du Git-Submodule eine Weile verwendet hast, wirst du feststellen, dass git subtree
viele Probleme mit dem Git-Submodul löst. Wie immer muss man bei Git eine Lernkurve durchlaufen, um die Funktion bestmöglich nutzen zu können.
Folge mir auf Twitter @durdn, wenn du mehr über Git erfahren möchtest. Und sieh dir Atlassian Bitbucket an, wenn du nach einem guten Tool zur Verwaltung deiner Git-Repositorys suchst.
Update: Nach Veröffentlichung dieses Beitrags habe ich auch einen Artikel über die Vorteile von git subtree geschrieben.
Diesen Artikel teilen
Nächstes Thema
Lesenswert
Füge diese Ressourcen deinen Lesezeichen hinzu, um mehr über DevOps-Teams und fortlaufende Updates zu DevOps bei Atlassian zu erfahren.