Strategie zur Verwendung der Versionskontrolle auf einem modularen System

15

Nehmen wir der Einfachheit halber an, wir haben eine Anwendung mit Client und Server. Gibt es eine bessere Idee, ein Repository für beide oder zwei separate Repositorys zu verwenden?

Wenn Sie sie mischen, ist es wahrscheinlich einfacher, korrelierte Änderungen zu verfolgen und korrelierte Verzweigungen (z. B. Protokollentwicklung) beizubehalten, aber andererseits wird die individuelle Entwicklung übersichtlicher.

mbq
quelle
Und was ist falsch daran, getrennte Zweige zu verwenden? Ein Entwickler muss nur die Filiale, an der er gerade arbeitet, lokal öffnen, damit er nicht einmal die Inhalte sieht, die ohnehin nur in den anderen Filialen vorhanden sind. Aber wenn er aus irgendeinem Grund in die Filiale muss, kann er es.
Spencer Rathbun
@SpencerRathbun - Die Verwendung solcher Zweige ist ein Rezept für eine Katastrophe . Es wäre wirklich schwierig, Dateien zwischen Server und Client auszutauschen, insbesondere Schnittstellen und Systemdokumentation usw. Bei einem DVCS müssten Sie alle Client- und Server-Commits klonen, auch wenn Sie nur eines wollten, und würden es Ihnen nicht geben Jeder Hinweis darauf, welche Client- und Serverversionen zusammenarbeiten würden. Im Vergleich zu einem monolithischen (Einzel-) Repository oder einer modularen (Mehrfach-) Repository-Aufteilung erhalten Sie tatsächlich das Schlimmste aus beiden Welten .
Mark Booth
@MarkBooth Humm, ich habe an Projektabschnitte in jedem Zweig gedacht, da er angedeutet hat, dass sie Code gemeinsam nutzen werden. Kennzeichnen Sie einfach jeden Abschnitt als die entsprechenden Zweige und Sie sind gut. Erlaubt Ihr DVCS nicht, dass eine Datei / ein Commit mehrere Tags enthält?
Spencer Rathbun

Antworten:

12

Wenn Sie Git oder Mercurial verwenden , sollten Sie sich Submodule oder Subrepositorys ansehen .

Der Client, der Server und die zugehörigen Schnittstellendateien befinden sich in eigenen Repositorys, sind jedoch auf der Super-Repository- Ebene miteinander verbunden. Dies würde es Ihnen ermöglichen, eine Prüfung auf der obersten Ebene durchzuführen und gitoder hgdas entsprechende Commit für jedes der Submodule / Subrepositories zu überprüfen.

Wenn Sie nur ein Commit für das Super-Repository durchführen, wenn Client und Server zueinander passen, können Sie mit dem Super-Repository immer nur ein funktionierendes System auschecken. Sie würden also niemals versuchen, den neuen Client auf einem alten Client auszuführen Server oder umgekehrt.

Submodule / Subrepositorys bieten Ihnen alle Vorteile der Verwendung separater Repositorys zusammen mit den Vorteilen eines einzelnen monolithischen Repositorys auf Kosten einer zusätzlichen Komplexität.

Diese Antwort ist nicht dazu gedacht, andere SCMs zu befürworten gitoder zu hgübertreffen. Es ist nur so, dass ich diese SCMs nur gut genug kenne, um zu wissen, dass diese Option existiert. Ich verstehe svnzum Beispiel nicht, wie Äußerlichkeiten funktionieren.

Mark Booth
quelle
1
Das ist ein interessantes Feature. Ich würde gerne einige Fallstudien sehen, von denen ich noch nicht einmal gehört habe!
Ed James
Ähnliches gilt für Subversion für externe Definitionen: svnbook.red-bean.com/de/1.0/ch07s03.html . Es funktioniert jedoch etwas anders.
Liori
1
@ MarkBooth: Ja, das kannst du. Auf dieser Seite sehen Sie Parameter, die aussehen wie -r12345 - diese definieren, welche Revision Sie erhalten möchten. Und da die Eigenschaft svn: externals wie jede Textdatei versioniert ist, können Sie für jede Revision unterschiedliche Werte für -r festlegen. Außerdem durchsuchen Sie die alte 1.0-Dokumentation. Externe Definitionen wurden in 1.5 geändert und die aktuelle Version ist 1.7. Siehe: svnbook.red-bean.com/en/1.7/svn.advanced.externals.html
liori
6

Trennen!

In der Tat hätte ich wahrscheinlich drei Repositorys, eines für den Client und die entsprechenden Nur-Client-Bibliotheken, eines für den Server (und die entsprechenden Bibliotheken) und eines für die gemeinsam genutzten Bibliotheken (einschließlich der API-Schnittstellen, die die Funktionalität zwischen den beiden offen legen) , plus allen anderen gemeinsam genutzten Code). Ich denke, das ist wirklich der Schlüssel, der gemeinsam genutzte Code sollte in einem eigenen separaten Repository gespeichert werden. Auf diese Weise können Sie sicherstellen, dass die Interoperabilität zwischen Client und Server immer auf dem gleichen Stand ist UND vom Design jedes einzelnen Verbrauchers isoliert ist.

Dies ist natürlich nicht immer möglich, je nach verwendetem Kommunikationsframework. Es ist jedoch wahrscheinlich, dass gemeinsam genutzter Code das Format der Datenübertragungsobjekte oder die Handshake-Schritte in Ihrem benutzerdefinierten Protokoll (oder einem anderen Beispiel) vorgibt. .

Angenommen, Sie haben eine recht ordentliche Continuous Integration und QA-Einrichtung (meiner Erfahrung nach eine ziemlich große Annahme, die ich jedoch machen werde. Wenn Sie keine QA-Abteilung haben, sollten Sie sich zumindest eine CI zulegen), sollten Sie nicht Sie müssen das Single-Repo-Muster nicht verwenden, um mögliche Codefehler zu vermeiden. Entweder zeigt Ihr CI-Server die Bibliotheksinteroperabilität an, oder Ihr QA-Team erkennt Laufzeitfehler (oder, noch besser, Ihre Komponententests).

Die Vorteile von geteilten Repositorys liegen in der Möglichkeit, separate Teile eines Systems zu versionieren. Möchten Sie eine Kopie des Servers der letzten Woche erstellen und mit dem Client dieser Woche ausführen, um zu versuchen, die Ursache eines Leistungsproblems zu ermitteln? Keine Bange.

Ed James
quelle
1

In Mercurial kann dieses Schema verwendet werden ->, um die Subrepo-Beziehung zu bezeichnen:

product -> client -|-> (many components)
                   |->  shared component A

        -> server -|-> (many components)
                   |->  shared component A

Produkt hat Subrepos Client, Server. Jeder von diesen hat seine Komponenten als Subrepos, möglicherweise mindestens ein Subrepo, das von beiden geteilt wird.

Das Markieren sollte wahrscheinlich auf den ersten beiden Ebenen erfolgen, nicht darunter.

Commits werden auf Komponentenebene durchgeführt, die Superrepos verfolgen effektiv benannte Zweige und Versionen des Produkts. Benannte Zweige / Lesezeichen sind in der Regel besser als Klonzweige, da sie benutzerfreundlich (dh trainierbar) und mit Subrepos kompatibel sind.

hg geht tendenziell davon aus, dass Superrepos das Produkt sind und Commits auf oberster Ebene durchgeführt werden. Dies funktioniert jedoch nicht besonders gut, wenn mehrere Produkte dieselben Komponenten verwenden. :-)

Ich denke nicht, dass dieses Schema viel ändern wird, wenn es auf Git umgestellt wird, aber ich habe es noch nicht in Git ausprobiert.

Paul Nathan
quelle
1

Dies ist ein Konfigurationsverwaltungsproblem, kein Versionskontrollproblem. Wie immer hämmert ein Programmierer mit einem Schraubendreher einen Nagel ein. Überlegen Sie, wie Sie Ihre Konfigurationen verwalten, die Revisionskontrolle kümmert sich um sich.

mattnz
quelle
1

Der einfachste Ansatz besteht darin, ein einziges Repository zu verwenden. Wenn Sie also Komplexität nicht aus Gründen der Komplexität bevorzugen, sollte dies die Standardauswahl sein, wenn keine zwingenden Argumente vorliegen.

Wird die Client- und Serverentwicklung von verschiedenen Organisationen durchgeführt? Wird es mehrere Implementierungen des Clients (oder Servers) geben? Ist der Client Open Source und die Server-Implementierung geheim? Wenn die Antwort auf all diese Fragen "Nein" lautet, ist es wahrscheinlich, dass alles, was komplexer ist als ein einzelnes Repository, nur Unannehmlichkeiten mit sich bringt, die keinen Nutzen bringen.

Wenn Sie sich dafür entscheiden, separate Codebasen zu verwalten, benötigen Sie klare Richtlinien zur Verwaltung, um Inkompatibilitäten und Abhängigkeiten zu vermeiden. Nachdem Sie die ersten Schluckaufe durchgearbeitet haben, stellen Sie möglicherweise fest, dass es am sichersten ist, beide Repositorys immer zusammen zu überprüfen, zusammen aufzubauen und zusammen bereitzustellen ... was offensichtlich den ganzen Zweck der Trennung zunichte macht!

Modularität ist eine nette Eigenschaft, aber das Aufteilen von Repositorys ist kein Werkzeug, um dies zu erreichen. Wie der vorherige Absatz impliziert, können Sie hochgradig gekoppelte Komponenten haben, die über mehrere Codebasen aufgeteilt sind (unerwünscht), und Sie können ebenfalls hochgradig modulare Komponenten innerhalb derselben Codebase haben (wünschenswert).

Bei mehr als einer Gelegenheit habe ich mich (erfolgreich) dafür ausgesprochen, dass mein Team vorhandene Git-Repositorys zusammenführt, da dies die Entwicklung und Bereitstellung vereinfacht.

Todd Owen
quelle
0

Vergiss das Repository für einen Moment. Wie würden Sie die beiden Projekte auf Ihrem Computer organisieren, wenn Sie sie mit niemandem teilen würden? Wie würde der Rest des Teams das machen? Würdest du...

  • Alle Quelldateien für Client und Server in dasselbe Verzeichnis stellen?

  • Ein Hauptprojektverzeichnis erstellen, das Unterverzeichnisse für den Client und den Server enthält?

  • Halten Sie die beiden Projekte vollständig getrennt?

Sobald Sie sich als Team darauf geeinigt haben, können Sie die Projekte in Ihr Code-Repository einchecken. Alle Werkzeuge zur Versionskontrolle, die mir einfallen, reproduzieren gerne jede Verzeichnisstruktur, die Sie mögen - es ist ihnen egal, welche Datei zu welchem ​​Projekt gehört. Abgesehen von geringfügigen administrativen Unterschieden ist der Unterschied zwischen einem oder zwei Repositorys (oder sechs) normalerweise nicht so groß.

Beispielsweise besteht bei Subversion der größte Unterschied zwischen separaten Repositorys für Client und Server und einem einzelnen kombinierten Repository darin, wie sich die Revisionsnummern ändern. Bei einem Single-Repository erhöht sich die Versionsnummer jedes Mal, wenn Sie Code an einen Client oder einen Server übergeben. Bei separaten Repositorys ändert ein Commit für das Serverprojekt nicht die Head-Revisionsnummer für den Client.

Caleb
quelle