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 P1
der Bibliotheken L1
, L2
und L3
. L1
verwendet auch L2
und L3
und L2
verwendet L3
auch. 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 P1
und L3
die die Benutzeroberfläche von ändern L3
. Fügen Sie nun Projekte P2
und P3
in 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?
- Implementieren Sie die neue Schnittstelle in
L3
- Machen Sie eine Pull-Anfrage für
L3
und warten Sie auf die Überprüfung - Führen Sie die Änderung zusammen
- Erstellen Sie eine neue Version von
L3
- Beginnen Sie mit der Arbeit an dem Feature in,
P1
indem Sie es auf dieL3
neue Version verweisen , und implementieren Sie dann das Feature imP1
Feature-Zweig - Stellen Sie eine Pull-Anfrage, lassen Sie diese überprüfen und zusammenführen
(Ich habe gerade bemerkt , dass ich zu wechseln vergessen L1
und L2
auf 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?