In git funktionierte die Versionierung für ein Dutzend Bibliotheken parallel

11

Wir machen Projekte, aber wir verwenden viel Code zwischen den Projekten wieder und haben viele Bibliotheken, die unseren gemeinsamen Code enthalten. Wenn wir neue Projekte implementieren, finden wir mehr Möglichkeiten, gemeinsamen Code herauszufiltern und in Bibliotheken abzulegen. Die Bibliotheken hängen voneinander ab, und die Projekte hängen von den Bibliotheken ab. Jedes Projekt und alle in diesem Projekt verwendeten Bibliotheken müssen dieselbe Version aller Bibliotheken verwenden, auf die sie sich beziehen. Wenn wir eine Software veröffentlichen, müssen wir Fehler beheben und möglicherweise für viele Jahre, manchmal für Jahrzehnte, neue Funktionen hinzufügen. Wir haben ungefähr ein Dutzend Bibliotheken, Änderungen betreffen häufig mehr als zwei Bibliotheken, und mehrere Teams arbeiten parallel an mehreren Projekten, wobei alle diese Bibliotheken gleichzeitig geändert werden.

Wir haben kürzlich auf git umgestellt und Repositorys für jede Bibliothek und jedes Projekt eingerichtet. Wir verwenden Stash als gemeinsames Repository, führen neue Funktionen für Feature-Zweige durch, stellen dann Pull-Anforderungen und führen diese erst nach Überprüfung zusammen.

Viele der Probleme, mit denen wir uns in Projekten befassen müssen, erfordern Änderungen in mehreren Bibliotheken und im spezifischen Code des Projekts. Dazu gehören häufig Änderungen an Bibliotheksschnittstellen, von denen einige nicht kompatibel sind. (Wenn Sie der Meinung sind, dass dies faul klingt: Wir arbeiten mit Hardware zusammen und verstecken bestimmte Hardware hinter generischen Schnittstellen. Fast jedes Mal, wenn wir die Hardware eines anderen Anbieters integrieren, stoßen wir auf Fälle, die unsere aktuellen Schnittstellen nicht erwartet haben, und müssen sie daher verfeinern.) Beispiel vorstellen , ein Projekt P1der Bibliotheken L1, L2und L3. L1verwendet auch L2und L3und L2verwendet L3auch. Das Abhängigkeitsdiagramm sieht folgendermaßen aus:

   <-------L1<--+
P1 <----+  ^    |
   <-+  |  |    |
     |  +--L2   |
     |     ^    |
     |     |    |
     +-----L3---+

Stellen Sie sich nun vor, eine Funktion für dieses Projekt erfordert Änderungen in P1und L3die die Benutzeroberfläche von ändern L3. Fügen Sie nun Projekte P2und P3in den Mix ein, die sich auch auf diese Bibliotheken beziehen. Wir können es uns nicht leisten, alle auf die neue Schnittstelle umzustellen, alle Tests auszuführen und die neue Software bereitzustellen. Was ist die Alternative?

  1. Implementieren Sie die neue Schnittstelle in L3
  2. Machen Sie eine Pull-Anfrage für L3und warten Sie auf die Überprüfung
  3. Führen Sie die Änderung zusammen
  4. Erstellen Sie eine neue Version von L3
  5. Beginnen Sie mit der Arbeit an dem Feature in, P1indem Sie es auf die L3neue Version verweisen , und implementieren Sie dann das Feature im P1Feature-Zweig
  6. Stellen Sie eine Pull-Anfrage, lassen Sie diese überprüfen und zusammenführen

(Ich habe gerade bemerkt , dass ich zu wechseln vergessen L1und L2auf die neue Version. Und ich weiß nicht einmal , wo diese in bleiben, weil es mit parallel durchgeführt werden müßte P1...)

Dies ist ein langwieriger, fehleranfälliger und sehr langer Prozess zur Implementierung dieser Funktion. Er erfordert unabhängige Überprüfungen (was die Überprüfung erheblich erschwert), lässt sich überhaupt nicht skalieren und wird uns wahrscheinlich aus dem Geschäft bringen, weil wir Seien Sie dabei so festgefahren, dass wir nie etwas erledigen.

Aber wie setzen wir Verzweigung und Tagging ein, um einen Prozess zu erstellen, mit dem wir neue Funktionen in neuen Projekten ohne allzu großen Aufwand implementieren können?

sbi
quelle
1
Das Ändern Ihrer Werkzeuge sollte sich nicht zu stark auf die vorhandenen Prozesse auswirken. Wie haben Sie mit diesem Problem umgegangen, bevor Sie zu Git gewechselt sind?
Bart van Ingen Schenau
Ist es möglich, der Schnittstelle einfach eine neue Methode hinzuzufügen, ohne die vorhandene zu beschädigen, wenn zu viele Bibliotheken davon abhängen? Normalerweise ist das nicht die beste Idee, aber zumindest können Sie damit die neue Funktion "implementieren" und die alte Methode jederzeit ablehnen, wenn ein freier Moment zur Verfügung steht. Oder sind diese Schnittstellen zu zustandsbehaftet, als dass solche "parallelen Schnittstellen" funktionieren könnten?
Ixrec
1
@Ixrec: Mir wurde gesagt, dass "dies nicht der richtige Weg ist", Dinge zu tun. Jeder verwendet individuelle Repositories für einzelne Projekte, daher wurde beschlossen, dass wir dies auch tun.
sbi
2
Ich würde argumentieren, dass es sich nicht um separate Projekte handelt, wenn sie häufig gemeinsam geändert werden müssen. Die Grenzen zwischen "Projekten" sollten immer eine Art langfristige Abwärtskompatibilitätsgarantie haben.
Ixrec
1
@Ixrec: Die Integration von mehr Hardware ähnelt der Portierung von Code auf mehr Plattformen: Je mehr Sie dies getan haben, desto weniger müssen Sie für eine weitere Hardware / Plattform ändern. Auf lange Sicht wird sich der Code also stabilisieren. Im Moment müssen wir jedoch einen Prozess finden, der es uns ermöglicht, lange genug auf dem Markt zu bleiben, um dorthin zu gelangen.
sbi

Antworten:

5

Hier wird das Offensichtliche herausgestellt, aber es lohnt sich vielleicht, es zu erwähnen.

Normalerweise werden Git-Repos pro Bibliothek / Projekt zugeschnitten, da sie in der Regel unabhängig sind. Sie aktualisieren Ihr Projekt und kümmern sich nicht um den Rest. Andere Projekte, die davon abhängen, aktualisieren einfach ihre Bibliothek, wann immer sie es für richtig halten.

Ihr Fall scheint jedoch stark von korrelierten Komponenten abhängig zu sein, sodass ein Merkmal normalerweise viele von ihnen betrifft. Und das Ganze muss als Bündel verpackt werden. Da für die Implementierung einer Funktion / Änderung / eines Fehlers häufig viele verschiedene Bibliotheken / Projekte gleichzeitig angepasst werden müssen, ist es möglicherweise sinnvoll, alle im selben Repo zu platzieren.

Dies hat starke Vor- und Nachteile.

Vorteile:

  • Rückverfolgbarkeit: Der Zweig zeigt alles an, was in jedem Projekt / jeder Bibliothek im Zusammenhang mit dieser Funktion / diesem Fehler geändert wurde.
  • Bündelung: Wählen Sie einfach ein Tag aus, und Sie erhalten alle Quellen richtig.

Nachteile:

  • Zusammenführen: ... manchmal ist es schon schwierig mit einem einzelnen Projekt. Wenn verschiedene Teams an gemeinsam genutzten Niederlassungen arbeiten, sollten Sie sich auf die Auswirkungen einstellen.
  • Gefährlicher "oops" -Faktor: Wenn ein Mitarbeiter das Repository durch einen Fehler durcheinander bringt, kann dies Auswirkungen auf alle Projekte und Teams haben.

Es liegt an Ihnen zu wissen, ob der Preis den Vorteil wert ist.

BEARBEITEN:

Es würde so funktionieren:

  • Feature X muss implementiert sein
  • Zweig erstellen feature_x
  • Alle beteiligten Entwickler arbeiten an diesem Zweig und arbeiten parallel daran, wahrscheinlich in dedizierten Verzeichnissen, die sich auf ihr Projekt / ihre Bibliothek beziehen
  • Sobald es vorbei ist, überprüfen Sie es, testen Sie es, verpacken Sie es, was auch immer
  • Füge es wieder im Master zusammen ... und dies kann der schwierige Teil seit der Zwischenzeit sein feature_yund wurde feature_zmöglicherweise auch hinzugefügt. Es wird eine "teamübergreifende" Fusion. Deshalb ist es ein schwerwiegender Nachteil.

Nur zur Veranschaulichung: Ich denke, dies ist in den meisten Fällen eine schlechte Idee und sollte mit Vorsicht durchgeführt werden, da der Nachteil der Zusammenführung normalerweise höher ist als der, den Sie durch Abhängigkeitsmanagement / ordnungsgemäße Funktionsverfolgung erhalten.

dagnelies
quelle
Danke, wir schauen uns das gerade an. Was ich vor diesem Hintergrund nicht verstehe, ist, wie wir uns mit Git verzweigen würden. In SVN bedeutet Verzweigungen, dass ein Teilbaum (im Repository) an eine andere Stelle (im Repository) kopiert wird. Auf diese Weise ist es einfach, Zweige eines beliebigen Teilbaums in Ihrem Repo zu erstellen. Wenn Sie also viele Projekte darin haben, können Sie jedes einzeln verzweigen. Gibt es so etwas in git, oder könnten wir immer nur ein ganzes Repo verzweigen?
sbi
@sbi: du würdest das ganze repo verzweigen. Sie können nicht mit Teilbäumen in verschiedenen Zweigen arbeiten, was den Punkt in Ihrem Fall irgendwie zunichte machen würde. Git "kopiert" jedoch nichts, sondern verfolgt einfach die Änderungen in dem Zweig, an dem Sie arbeiten.
Dagnelies
Daher muss jemand einen Feature-Zweig für eine Bibliothek erstellen, um auch alle anderen beim Zusammenführen oder erneuten Basieren zusammenzuführen. Dies ist ein echter Nachteil. (Übrigens, SVN macht auch immer nur faule Kopien.)
sbi
@sbi: siehe edit
dagnelies
1
Nun, derzeit fühlen sich die meisten von uns nicht wohl. :-/Darüber hinaus wissen selbst diejenigen, die es sind (und die auf den Wechsel zu Git drängten), nicht, wie wir unseren Entwicklungsprozess an Git anpassen können. Seufzer. Ich fürchte, es wird ein paar harte Monate dauern, bis die Dinge ruhiger werden. Trotzdem danke, deine ist die bisher hilfreichste Antwort.
sbi
4

Die Lösung, die Sie suchen, ist ein Abhängigkeitsmanagement-Tool in Abstimmung mit Git-Submodulen

Tools wie:

  • Maven
  • Ameise
  • Komponist

Mit diesen Tools können Sie Abhängigkeiten eines Projekts definieren.

Sie können verlangen, dass ein Submodul mindestens Version > 2.xx ist, oder einen Bereich von Versionen angeben , die kompatibel sind = 2.2. * Oder weniger als eine bestimmte Version <2.2.3

Wenn Sie eine neue Version eines der Pakete veröffentlichen, können Sie diese mit der Versionsnummer versehen. Auf diese Weise können Sie diese bestimmte Version des Codes in alle anderen Projekte einbinden

Patrick
quelle
Das Abhängigkeitsmanagement ist jedoch nicht unser Problem, es ist gelöst. Wir nehmen derzeit regelmäßig Änderungen in vielen Bibliotheken vor und müssen den Aufwand für die Erstellung neuer Versionen minimieren, während stabile Projektversionen beibehalten werden. Ihre Antwort scheint keine Lösung dafür zu bieten.
sbi
@sbi Dies würde den Aufwand für die Erstellung neuer Versionen und die Aufrechterhaltung stabiler Projektversionen verwalten. Da Sie festlegen können, dass Projekt x auf Projekt y Version 2.1.1 basiert, können Sie neue Versionen von Projekt y erstellen, die sich nicht auf Projekt x auswirken.
Patrick
Auch hier ist das Deklarieren von Abhängigkeiten nicht unser Problem. Das können wir schon. Das Problem besteht darin, wie Änderungen, die sich über mehrere Projekte / Bibliotheken erstrecken, effizient verwaltet werden können. Ihre Antwort kann dies nicht erklären.
sbi
@sbi: Also, was genau ist dein Problem? Sie nehmen Ihre Änderungen vor, stoßen die Version an, aktualisieren Abhängigkeiten bei Bedarf und voila. Was Sie in Ihrem ersten Beitrag beschrieben haben, ist typisch für Maven & Co. Zeug. Jede Distribution basiert auf klar definierten versionierten Bibliotheken. Wie könnte es klarer sein?
Dagnelies
@arnaud: Die Bearbeitungszeiten für einen solchen Prozess für (derzeit recht häufige) Änderungen, die drei oder mehr Schichten durchschneiden, würden uns umbringen. Ich dachte, meine Frage beschreibt das.
sbi
0

Submodule

Sie sollten versuchen, Submodule zu aktivieren , wie in einem Kommentar vorgeschlagen.

Wenn Projekt P1auf die drei Submodule bezieht L1, L2und L3speichert es tatsächlich einen Verweis auf bestimmte Commits in allen drei Repositories: diejenigen , die sind Arbeitsversionen der einzelnen Bibliotheken für dieses Projekt .

So können mehrere Projekte mit mehreren Submodulen arbeiten: Sie P1beziehen sich möglicherweise auf die alte Version der Bibliothek, L1während das Projekt P2die neue Version verwendet.

Was passiert, wenn Sie eine neue Version von liefern L3?

  • neue Schnittstelle implementieren in L3
  • Festschreiben, Testen , Pull-Anfrage stellen, Überprüfen, Zusammenführen, ... (Sie können dies nicht vermeiden)
  • sicherstellen, L2funktioniert mit L3, verpflichten, ...
  • sicherstellen L1funktioniert mit neuen L2, ...
  • Stellen Sie sicher, dass P1mit den neuen Versionen aller Bibliotheken funktioniert:
    • innen P1‚s lokale Arbeitskopie L1, L2und L3, fetche die Änderungen , die Sie interessieren.
    • Änderungen festschreiben, git add L1 L2 L3um den neuen Verweis auf Module festzuschreiben
    • Pull-Anfrage für P1, Test, Überprüfung, Pull-Anfrage, Zusammenführen ...

Methodik

Dies ist ein langwieriger, fehleranfälliger und sehr langer Prozess zur Implementierung dieser Funktion. Er erfordert unabhängige Überprüfungen (was die Überprüfung erheblich erschwert), lässt sich überhaupt nicht skalieren und wird uns wahrscheinlich aus dem Geschäft bringen, weil wir Seien Sie dabei so festgefahren, dass wir nie etwas erledigen.

Ja, es sind unabhängige Überprüfungen erforderlich , da Sie Folgendes ändern:

  • die Bibliothek
  • Bibliotheken, die davon abhängen
  • Projekte, die von mehreren Bibliotheken abhängen

Würden Sie aus dem Geschäft geraten, weil Sie Mist liefern? (Vielleicht eigentlich gar nicht). Wenn ja, müssen Sie Tests durchführen und Änderungen überprüfen.

Mit geeigneten Git-Tools (sogar gitk) können Sie leicht sehen, welche Versionen der Bibliotheken jedes Projekt verwendet, und Sie können sie unabhängig von Ihren Anforderungen aktualisieren. Submodule sind perfekt für Ihre Situation und verlangsamen Ihren Prozess nicht.

Vielleicht können Sie einen Weg finden, einen Teil dieses Prozesses zu automatisieren , aber die meisten der oben genannten Schritte erfordern menschliches Gehirn. Der effektivste Weg, um Zeit zu sparen, besteht darin, sicherzustellen, dass Ihre Bibliotheken und Projekte einfach weiterzuentwickeln sind. Wenn Ihre Codebasis neue Anforderungen problemlos bewältigen kann, sind Codeüberprüfungen einfacher und nehmen wenig Zeit in Anspruch.

(Bearbeiten) Eine andere Sache, die Ihnen helfen könnte, ist das Gruppieren verwandter Codeüberprüfungen. Sie übernehmen alle Änderungen und warten, bis Sie diese Änderungen an alle Bibliotheken und Projekte weitergegeben haben, die sie verwenden, bevor Sie Pull-Anforderungen ausführen (oder bevor Sie sich um sie kümmern). Am Ende führen Sie eine größere Überprüfung für die gesamte Abhängigkeitskette durch. Vielleicht kann dies Ihnen helfen, Zeit zu sparen, wenn jede lokale Änderung klein ist.

Core-Dump
quelle
Sie beschreiben, wie Sie das Abhängigkeitsproblem lösen können (das wir, wie ich bereits sagte, gelöst haben) und genau das Problem negieren, das wir haben. Warum störst du dich überhaupt? (FWIW, wir schreiben Software, die Kraftwerke antreibt. Sauberer, sicherer und gründlich überprüfter Code ist eine
Hauptfunktion
@sbi Was sind Submodule, wenn nicht ein Sonderfall von Verzweigung und Tagging? Sie denken, bei Submodulen geht es um das Abhängigkeitsmanagement, da sie auch Abhängigkeiten verfolgen. Aber sicher, bitte erfinden Sie Submodule mit Tags neu, wenn Sie wollen, es macht mir nichts aus. Ich verstehe Ihr Problem nicht: Wenn überprüfter Code eine Hauptfunktion ist, müssen Sie einige Zeit für Überprüfungen einplanen. Sie sind nicht festgefahren, Sie gehen so schnell wie möglich mit den Einschränkungen, die Ihnen auferlegt werden.
Coredump
Bewertungen sind uns sehr wichtig. Dies ist einer der Gründe, warum wir besorgt sind, dass ein Problem (und seine Überprüfungen) für mehrere Änderungen in mehreren Repositorys auf mehrere Überprüfungen aufgeteilt wird. Außerdem möchten wir uns nicht in einem Problem festsetzen, weil wir lieber die Zeit damit verbringen, Code zu schreiben und zu überprüfen. Zu Submodulen: Bisher habe ich nur von ihnen gehört: "Mach dir keine Sorgen, das ist nicht der richtige Weg". Nun, da unsere Anforderungen so einzigartig zu sein scheinen, sollten wir diese Entscheidung vielleicht noch einmal
überdenken
0

Ich verstehe also, dass Sie für P1 die L3-Schnittstelle ändern möchten, aber Sie möchten, dass sich die anderen P2 und P3, die von der L3-Schnittstelle abhängen, sofort ändern. Dies ist ein typischer Fall von Abwärtskompatibilität. Es gibt einen schönen Artikel über die Wahrung der Abwärtskompatibilität

Es gibt verschiedene Möglichkeiten, dies zu lösen:

  • Sie müssen jedes Mal neue Schnittstellen erstellen, um die alten Schnittstellen zu erweitern.

ODER

  • Wenn Sie alte Schnittstellen nach einiger Zeit deaktivieren möchten, können Sie mehrere Schnittstellenversionen verwenden. Sobald alle abhängigen Projekte verschoben wurden, entfernen Sie die älteren Schnittstellen.
Uday Shankar
quelle
1
Nein, die Abwärtskompatibilität wird durch Release-Zweige sichergestellt und ist nicht unser Problem. Das Problem ist, dass wir auf einer sich schnell ändernden Codebasis sitzen, die sich jetzt in Bibliotheken aufteilen möchte, obwohl sich die Schnittstellen noch in der Phase befinden, in der sie sich häufig ändern. Ich weiß, wie man solche Bestien in SVN verwaltet, aber ich weiß nicht, wie man das in Git macht, ohne in der Verwaltung zu ertrinken.
sbi
0

Wenn ich Ihr Problem richtig verstehe:

  • Sie haben 4 miteinander verbundene Module, P1 und L1 bis L3
  • Sie müssen eine Änderung an P1 vornehmen, die sich letztendlich auf L1 bis L3 auswirkt
  • Es zählt als Prozessfehler, wenn Sie alle 4 zusammen ändern müssen
  • Es gilt als Prozessfehler, wenn Sie alle 1 zu 1 ändern müssen.
  • Dies gilt als Prozessfehler, wenn Sie die Blöcke, in denen Änderungen vorgenommen werden müssen, im Voraus identifizieren müssen.

Das Ziel ist also, dass Sie P1 und L1 auf einmal und einen Monat später L2 und L3 auf einmal ausführen können.

In der Java-Welt ist dies trivial und möglicherweise die Standardarbeitsweise:

  • Alles befindet sich in einem Repository ohne relevante Verwendung der Verzweigung
  • Module werden von maven basierend auf Versionsnummern kompiliert und miteinander verknüpft, nicht aufgrund der Tatsache, dass sich alle im selben Verzeichnisbaum befinden.

Sie können also den Code für L3 auf Ihrer lokalen Festplatte haben, der nicht kompiliert werden würde, wenn er gegen die Kopie von P1 im anderen Verzeichnis auf Ihrer Festplatte kompiliert würde. Zum Glück ist das nicht so. Java kann dies problemlos tun, da beim Kompilieren / Verknüpfen von Geschichten kompilierte JAR-Dateien und kein Quellcode verwendet werden.

Mir ist keine bereits vorhandene, weit verbreitete Lösung für dieses Problem in der C / C ++ - Welt bekannt, und ich würde mir vorstellen, dass Sie kaum die Sprache wechseln möchten. Aber etwas könnte leicht zusammen mit Make-Dateien gehackt werden, die das Gleiche tun:

  • installierte Bibliotheken + Header in bekannten Verzeichnissen mit eingebetteten Versionsnummern
  • Die Compilerpfade pro Modul wurden in das Verzeichnis für die entsprechenden Versionsnummern geändert

Sie könnten sogar die C / C ++ - Unterstützung in maven verwenden , obwohl die meisten C-Entwickler Sie seltsam ansehen würden, wenn Sie ...

soru
quelle
"Es zählt als Prozessfehler, wenn Sie alle 4 zusammen ändern müssen" . Eigentlich würde es nicht. Genau das haben wir mit SVN gemacht.
sbi
In diesem Fall ist es wohl kein Problem, einfach alle Projekte in das Repository zu stellen.
Soru
Wir prüfen derzeit, ob die Bibliotheken nur in zwei Repositorys gespeichert werden können. Das ist immer noch mehr als eine, aber viel weniger als "eine für jedes Projekt", und die Bibliotheken können sehr gut in zwei Gruppen aufgeteilt werden. Danke für deinen Beitrag!
sbi
PS: "Ich würde mir vorstellen, dass Sie kaum die Sprache wechseln wollen." Das ist eingebettetes Zeug. :)
sbi
-1

Es gibt eine einfache Lösung: Release-Zweige über das gesamte Repository hinweg schneiden, alle Fixes mit allen aktiv ausgelieferten Releases zusammenführen (es ist einfach, wenn dies in Git möglich sein sollte).

Alle Alternativen werden im Laufe der Zeit und mit dem Projektwachstum ein schreckliches Durcheinander verursachen.

zzz777
quelle
Könnten Sie bitte näher darauf eingehen? Ich bin mir nicht sicher, was Sie vorschlagen.
sbi
Im Klartext definieren Sie einen Verzweigungspunkt als Basisverzweigung und Zeitstempel. Sie haben folgende Hierarchie: Basiszweig -> Release-Entwicklungszweig -> privater Entwicklungszweig. Die gesamte Entwicklung erfolgt in privaten Filialen und wird dann in der Hierarchie zusammengeführt. Kunden-Release-Zweige sind vom Release-Entwicklungszweig abgebrochen. Ich bin mit Git nicht so vertraut, aber es scheint das Beste zu sein, was bei freien Versionsverwaltungssystemen der Fall ist.
zzz777
Eine sorgfältige Lektüre meiner Frage hätte Ihnen zeigen müssen, dass wir Probleme mit dem Overhead haben, der mit der Weitergabe von Änderungen zwischen Repositorys verbunden ist. Dies hat nichts mit Ihrer Antwort zu tun.
sbi
@sbi Es tut mir leid, dass ich deine Frage falsch verstanden habe. Und ich fürchte, Sie werden früher oder später einem schrecklichen Durcheinander gegenüberstehen.
zzz777