Wählen Sie zwischen einzelnen oder mehreren Projekten in einem Git-Repository?

223

In einer gitUmgebung, in der wir die meisten Projekte modularisiert haben, haben wir es mit einem Projekt pro Repository oder mit mehreren Projekten pro Repository- Designproblem zu tun . Betrachten wir ein modularisiertes Projekt:

myProject/
   +-- gui
   +-- core
   +-- api
   +-- implA
   +-- implB

Heute haben wir ein Projekt pro Repository . Es gibt Freiheit zu

  • release Einzelkomponenten
  • tag Einzelkomponenten

Es ist jedoch auch umständlich für branchKomponenten, da für das Verzweigen häufig apigleichwertige Verzweigungen coreund möglicherweise andere Komponenten erforderlich sind .

Wenn wir releaseeinzelne Komponenten benötigen, können wir dennoch die gleiche Flexibilität erzielen, indem wir mehrere Projekte pro Repository- Design verwenden.

Welche Erfahrungen gibt es und wie / warum haben Sie diese Themen angesprochen?

Johan Sjöberg
quelle
1
Ich habe gerade ein sehr ähnliches Problem. Ich muss verschiedene Versionen eines Projekts freigeben, damit sie sich in verschiedenen Repositorys befinden. Dies ist jedoch ein Albtraum. Es wäre großartig, wenn es eine Möglichkeit gäbe, nur Unterverzeichnisse zu verzweigen.
Andrew T Finnell
1
Jedes Modul muss separate Versionsnummern haben. Und wir nutzen git-describe.
2.
Ich bin überrascht zu sehen, dass Bit ( bitsrc.io ) und Lerna ( github.com/lerna/lerna ) nicht erwähnt werden! Sie können hier mehr erfahren: hackernoon.com/
Yoni

Antworten:

199

Es gibt drei Hauptnachteile one project per repository, wie Sie es oben beschrieben haben. Diese sind weniger zutreffend, wenn es sich um wirklich unterschiedliche Projekte handelt, aber von den Klängen her erfordern Änderungen an einem oft Änderungen an einem anderen, was diese Probleme wirklich übertreiben kann:

  1. Es ist schwerer zu entdecken, wann Bugs eingeführt wurden. Tools wie git bisectwerden viel schwieriger zu verwenden, wenn Sie Ihr Repository in Unter-Repositorys aufteilen. Es ist möglich, es ist einfach nicht so einfach, was bedeutet, dass die Fehlersuche in Krisenzeiten viel schwieriger ist.
  2. Das Verfolgen des gesamten Verlaufs eines Features ist viel schwieriger. Geschichte Verfahrbefehle wie git lognur nicht ausgeben Geschichte als sinnvoll mit gebrochenen Repository - Strukturen. Sie können einige nützliche Ausgaben mit Submodulen oder Teilbäumen oder über andere skriptfähige Methoden erhalten, aber es ist einfach nicht dasselbe wie das Eingeben tig --grep=<caseID>oder git log --grep=<caseID>Scannen aller Commits, die Sie interessieren. Ihre Geschichte wird schwerer zu verstehen, was sie weniger nützlich macht, wenn Sie sie wirklich brauchen.
  3. Neue Entwickler verbringen mehr Zeit mit dem Erlernen der Versionskontrollstruktur, bevor sie mit dem Codieren beginnen können. Jeder neue Job erfordert das Aufnehmen von Prozeduren, aber das Aufbrechen eines Projekt-Repositorys bedeutet, dass die VC-Struktur zusätzlich zur Architektur des Codes aufgenommen werden muss. Nach meiner Erfahrung ist dies besonders schwierig für Entwickler, die noch keine Erfahrung mit Git haben und aus traditionelleren, zentralisierten Shops stammen, die ein einziges Repository verwenden.

Am Ende ist es eine Opportunitätskostenkalkulation. Bei einem ehemaligen Arbeitgeber hatten wir unsere Hauptanwendung in 35 verschiedene Sub-Repositories aufgeteilt. Darüber hinaus haben wir einen komplizierten Satz von Skripten verwendet, um den Verlauf zu durchsuchen, um sicherzustellen, dass der Status (dh Produktions- und Entwicklungszweige) auf beiden Seiten identisch ist, und um sie einzeln oder in großen Mengen bereitzustellen.

Es war einfach zu viel; zumindest zu viel für uns. Der Verwaltungsaufwand machte unsere Funktionen weniger flink, die Bereitstellung viel schwieriger, das Unterrichten neuer Entwickler zu zeitaufwändig, und am Ende konnten wir uns kaum noch erinnern, warum wir das Repository überhaupt aufgebrochen hatten. An einem schönen Frühlingstag habe ich 10 US-Dollar für einen Nachmittag Cluster-Computing-Zeit in EC2 ausgegeben. Ich habe die Repos zusammen mit ein paar Dutzend git filter-branchAnrufen zurückgewebt. Wir haben nie zurückgeschaut.

Christopher
quelle
7
Abgesehen von einem Off-Topic gibt es für einen Repository-Manager nur wenige Dinge, die angenehmer sind, als Zeit auf einem System zu kaufen, das in zwei Stunden das schafft, was Ihr Laptop in 20 Stunden nicht kann, und das zu einem günstigeren Preis als das Mittagessen. Manchmal liebe ich das Internet wirklich.
Christopher
2
Wie würden Sie diese einzelnen Projekte als separate Releases veröffentlichen? Oder müssen Sie das nie tun? Das ist das Problem, das ich habe. Mit, wenn Sie eine V1 von Projekt A und eine V2 von Projekt B erstellen müssen.
Andrew T Finnell
5
Zum Bewegen zwischen dem „ein Projekt pro Repo“ und „multiple repos“ betrachten git-Teilbaum (gute Erklärung bei stackoverflow.com/a/17864475/15585 )
deterb
1
Ich habe ein Skript geschrieben, um dies für allgemeine Anwendungsfälle zu automatisieren: github.com/Oakleon/git-join-repos
chrishiestand
Was ist eine "VC-Struktur"?
Robert Harvey
60

Christopher hat die Nachteile eines Ein-Projekt-pro-Repository-Modells sehr gut aufgezählt. Ich möchte einige der Gründe erörtern, aus denen Sie einen Ansatz mit mehreren Repositorys in Betracht ziehen könnten. In vielen Umgebungen, in denen ich gearbeitet habe, war ein Ansatz mit mehreren Repositorys eine vernünftige Lösung, aber die Entscheidung, wie viele Repositorys vorhanden sind und wo die Kürzungen vorgenommen werden müssen, war nicht immer einfach.

In meiner aktuellen Position habe ich ein gigantisches CVS-Repository mit einem einzigen Repository und einer über zehnjährigen Geschichte in eine Reihe von Git-Repositorys migriert. Seit dieser anfänglichen Entscheidung ist die Anzahl der Repositories (durch die Aktionen anderer Teams) so weit gestiegen, dass ich den Verdacht habe, dass wir mehr haben, als optimal wäre. Einige Neueinstellungen haben vorgeschlagen, die Repositories zusammenzulegen, aber ich habe mich dagegen ausgesprochen. Das Wayland-Projekt hat eine ähnliche Erfahrung. In einem Vortrag, den ich kürzlich gesehen habe, hatten sie zu einem bestimmten Zeitpunkt über 200 Git-Repositories, für die sich die Leitung entschuldigte. Wenn ich auf ihre Website schaue , sehe ich, dass sie jetzt bei 5 sind, was vernünftig erscheint. Es ist wichtig zu beachten, dass das Zusammenfügen und Aufteilen von Repositorys eine überschaubare Aufgabe ist und es in Ordnung ist, (im Rahmen der Vernunft) zu experimentieren.

Wann möchten Sie möglicherweise mehrere Repositorys?

  1. Ein einziges Repository wäre zu groß, um effizient zu sein.
  2. Ihre Repositorys sind lose gekoppelt oder entkoppelt.
  3. Ein Entwickler benötigt in der Regel nur einen oder einen kleinen Teil Ihrer Repositorys, um zu entwickeln.
  4. In der Regel möchten Sie die Repositorys unabhängig voneinander entwickeln und müssen sie nur gelegentlich synchronisieren.
  5. Sie möchten mehr Modularität fördern.
  6. Verschiedene Teams arbeiten an verschiedenen Repositories.

Die Punkte 2 und 3 sind nur dann von Bedeutung, wenn Punkt 1 zutrifft. Durch die Aufteilung unserer Repositorys habe ich die Verzögerungen für unsere externen Kollegen erheblich verringert, den Festplattenverbrauch gesenkt und den Netzwerkverkehr verbessert.

4 und 5 sind subtiler. Wenn Sie die Repos von beispielsweise einem Client und einem Server aufteilen, ist die Koordinierung von Änderungen zwischen dem Client- und dem Server-Code teurer. Dies kann insofern positiv sein, als eine entkoppelte Schnittstelle zwischen beiden gefördert wird.

Selbst mit den Nachteilen von Multi-Repository-Projekten wird auf diese Weise viel seriöse Arbeit geleistet - Wayland und Boost kommen in den Sinn. Ich glaube nicht, dass sich ein Konsens in Bezug auf Best Practices entwickelt hat, und ein gewisses Urteilsvermögen ist erforderlich. Tools für die Arbeit mit mehreren Repositorys (Git-Teilbaum, Git-Submodul und andere) werden noch entwickelt und getestet. Mein Rat ist, zu experimentieren und pragmatisch zu sein.

Spacemoose
quelle
7
Diese Antwort wäre umso hilfreicher, wenn die Behauptung untermauert wird: "Das Zusammenfügen und Aufteilen von Repositorys ist eine überschaubare Aufgabe."
Wildcard
3
Mehrere Repos können auch gegen die Modularität wirken, da sie das Ändern von gemeinsam genutztem Code erschweren. Repo-übergreifende Abhängigkeiten erschweren die Integration, können Code leichter beschädigen (auch wenn Sie über gute Tools verfügen, um dies zu überprüfen), und die Gefahr, Repo-übergreifenden Code zu beschädigen, erschwert die Umgestaltung von Schnittstellen, die eines Ihrer leistungsstärksten Tools für die Erstellung von Dingen ist modularer.
Curt J. Sampson
Hier stimmt alles über MicroServices und DDD-Design. Sie sollten gemeinsam genutzten Code minimieren.
Arwin
49

Da wir GitHub verwenden, haben wir tatsächlich mehrere Projekte in einem Repo, aber stellen Sie sicher, dass diese Projekte / Module ordnungsgemäß modularisiert sind (wir verwenden -api und -core-Konventionen + Maven + statische und Laufzeitprüfung und gehen möglicherweise eines Tages sogar zu OSGi, um zu booten). .

Was spart es? Nun, wir müssen nicht mehrere Pull-Requests ausgeben, wenn wir etwas Kleines über mehrere Projekte hinweg ändern. Probleme und Wiki werden zentralisiert usw.

Wir behandeln jedes Modul / Projekt weiterhin als eigenständiges Projekt und erstellen und integrieren sie separat in unseren CI-Server usw.

Martijn Verburg
quelle
1
Sehr interessant. Ich würde vermuten, dass dies ein gängiges Modell für Github ist. Wenn Sie mit einzelnen Komponenten-Releases konfrontiert sind, setzen Sie etwas wie submodulesdas gesamte Repository ein oder geben es frei / markieren Sie es?
Johan Sjöberg
Submodule, wenn wir müssen, aber für jetzt versionieren wir vom Elternteil abwärts.
Martijn Verburg
Bei meinem jetzigen Arbeitgeber verwenden wir eine ähnliche Strategie und packen Metadaten über das letzte Commit in einem Projekt in die verschiedenen Manifestdateien von Artefakten (dh die Ergebnisse von git log -1 -- <project_dir>). Es ist wirklich ganz toll. Diese Antwort verdient mehr Gegenstimmen.
Christopher
22

Der Hauptunterschied bei der Verwendung eines oder mehrerer Repositorys besteht für mich in den Antworten auf die folgenden Fragen:

  • Sind die verschiedenen Teile von demselben Team entwickelt worden, haben sie denselben Release-Zyklus und denselben Kunden? Dann gibt es weniger Gründe, das eine Repository aufzuteilen.
  • Sind die verschiedenen Teile stark voneinander abhängig? Die Aufteilung von Modell, Controller und Benutzeroberfläche (auch wenn es sich um unterschiedliche Teile handelt) ist daher aufgrund der hohen Abhängigkeit voneinander nicht sehr sinnvoll. Wenn jedoch 2 Teile nur eine kleine Abhängigkeit haben, die durch eine stabile Schnittstelle implementiert wird, die nur alle paar Jahre geändert wird, ist es ratsam, die 2 Teile in 2 Repositorys zu unterteilen.

Nur als Beispiel habe ich eine kleine Anwendung (nur Client), die die "Qualität" eines Subversion-Repository überprüft. Es gibt die Kernimplementierung, die von der Befehlszeile aus gestartet werden kann und gut mit Java 6 funktioniert. Ich habe jedoch damit begonnen, eine Benutzeroberfläche zu implementieren, die JavaFX als Teil von Java 8 verwendet. Ich habe also die 2 geteilt und eine erstellt zweites Repository (mit einem zweiten Build-Prozess), mit abweichendem Zeitplan, ...

Ich mag die Antworten oben (habe sie hochgestuft), aber ich denke, sie sind nicht die ganze wahre Geschichte. Daher wollte ich auch die Argumente für die Aufteilung von Repositorys hinzufügen. Die eigentliche Antwort (wann man sich trennt) könnte also irgendwo in der Mitte sein ...

mliebelt
quelle
0

In Ihrem Beispiel sollten die Repositorys in Bezug auf ihre gegenseitige Abhängigkeit eingerichtet werden. Hier gelten alle Überlegungen zum Entwerfen von MicroServices und Domain Driven Design: In einigen Fällen ist doppelter Code akzeptabel, arbeiten Sie mit Schnittstellen, brechen Sie die Kompatibilität nicht, es sei denn, Sie müssen dies wirklich tun, usw.

Aus meiner Sicht sollte eine Benutzeroberfläche jetzt unabhängig vom Backend sein. Ein UI-Projekt-Repository sollte daher normalerweise den UI-Code und den Client-Controller enthalten. Der Client-Controller stellt eine abstrakte Verbindung mit den Service-Controllern her. Sie verwenden eine Service-Client- / API-Abstraktion, die separat vom Service versioniert wird, sodass ein Service aktualisiert werden kann, ohne die Clients zu beschädigen (es können mehrere verschiedene Clients vorhanden sein).

Ein Service selbst sollte also ein eigenes Repository sein. Meiner Ansicht nach handelt es sich bei dem Service nur um eine Zusammenfassung der Geschäftslogik mit einem einzigen Ansatzpunkt. Daher sollte die Geschäftslogik in der Regel von der Service-Technologie, die sie hostet, getrennt sein. Andererseits ist die Repository-Implementierung in der Regel so eng mit der Geschäftslogik verbunden, dass diese in dasselbe Repository integriert werden könnte. Aber auch dort kann Ihr Kilometerstand variieren.

Natürlich können einfache Projekte, die sich technologisch kaum ändern oder mehrere Stacks unterstützen, bei denen alle Benutzeroberflächen von derselben Quelle gehostet werden können wie das Back-End und die Back-End-Dienste in der Regel nur von demselben Client verwendet werden, von mehr profitieren fest integrierte Repositories.

In diesem Fall ist es wahrscheinlich in Ordnung, nur die volle Vertikale in einem Repository zu haben und sich darauf zu konzentrieren, sicherzustellen, dass Ihre funktionalen Domänen in ihrem eigenen Repository ordnungsgemäß eigenständig sind. Sie haben dann noch die meisten Vorteile kleinerer Repositories und sonst wenig Overhead.

Arwin
quelle