Softwareprojekte, die SVN als Versionskontrollsystem nutzen und modular aufgebaut sind, profitieren davon, einzelnen Module unter einem Parent-Repository gemeinsam zu verwalten. In SVN ist es daher üblich, eine Projektstruktur zu verwenden, die eine klare Trennung der Module ermöglicht.

Diese Struktur bietet besonders bei der separaten Veröffentlichung von Komponenten Vorteile. So kann beispielsweise ein Bugfix in „Modul A“ ausgerollt werden, ohne das gesamte Projekt neu veröffentlichen (releasen) zu müssen. Die CI/CD-Pipelines solcher Projekte sind speziell für diese Struktur ausgelegt. Eine geplante Migration von SVN zu Git stellt das Projektteam dann vor eine Herausforderung. Sie müssen die Struktur in Git abbilden, ohne hohe Kosten für den Umbau des Projekts und der CI/CD-Pipelines zu verursachen.
Eine einfache Lösung ist, die Module als separate Repositories zu pflegen. Das ist jedoch schlecht skalierbar. Wenn ein Projekt mehrere hundert Module umfasst, muss eine gemeinsame Verwaltung möglich sein.
Git bietet zwei Tools, die dieses Problem lösen können: Git Submodules und Git Subtree. Beide stellen die notwendigen Funktionen bereit, um die modulare Struktur beizubehalten und eine gemeinsame Verwaltung zu ermöglichen.
Sowohl Git Submodules als auch Git Subtree bilden jedes Modul als eigenständiges Repository ab. Die unabhängigen Repositories ermöglichen es den Entwicklenden, die Vorteile des modulbasierten Veröffentlichens zu nutzen.
Unterschiede Submodules und Subtree
Auf den ersten Blick scheinen sich die Tools sehr ähnlich zu sein, es gibt jedoch grundlegende Unterschiede, vor allem in der Handhabung. So zeichnet sich Git Subtree dadurch aus, dass das übergeordnete Repository den gesamten Code der Module enthält. Somit funktioniert das Repository im täglichen Gebrauch wie ein normales Git Repository. Im Gegensatz dazu speichert Git Submodules nur eine Referenz auf die Repositories der einzelnen Module, was die Entwicklenden bei ihrer täglichen Arbeit berücksichtigen müssen. Das Remote Parent Repository enthält keine physischen Kopien der Module. Nur für die lokale Entwicklung werden die Module beim Auschecken aus dem übergeordneten Repository als physische Ordner erstellt.
Die notwendigen Befehle finden sich in der Git-Dokumentation. Der größte Unterschied in der Bedienung besteht darin, dass bei Git Subtree die Änderungen in das übergeordnete Repository committet werden und die einzelnen Module bei Bedarf synchronisiert werden. Während bei Git Submodules die Änderungen in die Modul Repositories eingecheckt werden und nur die Commit Referenz im übergeordneten Repository aktualisiert wird. Das bedeutet, dass man mit Git Subtree in seinem Repository Branches vom übergeordneten Repository erstellen kann, die dann alle Module enthalten. Mit Git Submodules ist dies nicht möglich, hier muss man für jedes Modul eigene Branches angelegen. Je nach Projektumgebung und gewählter Arbeitsweise kann es vorteilhafter sein, das gesamte Repository zu branchen oder nur einzelne Branches anzulegen.1
Hinsichtlich der Benutzerfreundlichkeit der beiden Umsetzungen hat Git Subtree den Vorteil, dass in der täglichen Arbeit weniger Befehle benötigt werden, da die Entwickelnden Befehle wie commit und push im übergeordneten Repository ausführen können. Auf der anderen Seite beschränken sich Probleme bei Git Submodules auf einzelne Module und sind daher möglicherweise einfacher zu handhaben.
Entscheidung
Die Entscheidung zwischen diesen beiden Ansätzen muss je nach Projekt sorgfältig abgewogen werden eine generelle Empfehlung kann nicht ausgesprochen werden. Sowohl mit Git Subtree als auch mit Git Submodules können modulare Repositories in einem Git Repository verwaltet werden während eine separate Veröffentlichung möglich ist. Es ist jedoch zu beachten, dass beide Umsetzungen einen gewissen Overhead mit sich bringen und die Verwaltung im Vergleich zu einem Standard Git Repo erschweren.



