Git-Workflow - wer hat eine Idee?

Exterior

Lt. Junior Grade
Registriert
Nov. 2012
Beiträge
338
Hallo zusammen,

ich habe mal eine Frage zu Git und hoffe, jemand hat vielleicht ein paar zündende Ideen.

Wir setzen bei unserer Arbeit Git als Versionskontrolle ein. Das klappt an sich auch wunderbar.
Wir haben viele verschiedene Kunden und für jeden Kunden gibt es zwei Bestandteile:

  • kundenspezifischer Projekt-Teil
  • globaler Projektteil
Der kundenspezifische Teil existiert für jeden Kunden einzeln. Dort werden konfigurationen und Klassen-Ableitungen vorgenommen, die nur für den Kunden relevant sind.

Der globale Teil enthält alle globalen Funktionen und Codes und ist kundenübergreifend identisch. Es gibt also mehrere Kunden-Teile und einen globalen Teil, der in jedes Kunden-Projekt eingebunden wird.

Nun stehen wir aber vor folgendem Problem, ich stelle hier mal ein Beispiel auf:

Es gibt die Kunden A und B, beide verwenden den globalen Teil in Version 2.4 - diese Version ist bei beiden Kunden im Test- und im Livesystem installiert.

Kunde A meldet einen Fehler, also erstellen wir einen Branch, beheben den Fehler und mergen das ganze wieder in den globalen Teil Version 2.4 und rollen das als Version 2.4.1 bei Kunde A im Testsystem aus.

Danach meldet Kunde B einen Fehler, also erstellen wir einen Branch, beheben den Fehler und mergen das ganze wieder in den globalen Teil Version 2.4 und rollen das als Version 2.4.2 bei Kunde B im Testsystem aus. Dabei ist natürlich der Bugfix von Kunde A auch enthalten.

Nun gibt Kunde B den Bugfix frei und möchte, dass das ganze im Livesystem installiert wird. Leider wurde der Bugfix von Kunde A noch nicht freigegeben. Ohne eine solche Freigabe sollen diese Sachen nicht installiert werden. Also muss Kunde B nun darauf warten, dass Kunde A in seinem System den Bugfix freigibt, obwohl die Kunden gar nichts voneinander wissen bzw. nichts miteinander zu tun haben.

Die große Frage ist: Hat jemand eine Idee, wie man diesen Workflow verbessern könnte, damit man nicht vor diesem Problem steht?

Ich muss noch anmerken, dass diese Beispiele stark vereinfacht sind. In der Regel sind es nicht ein oder zwei andere Tickets, auf die noch gewartet werden muss, sondern eher mal 10 oder 20. Außerdem sind das nicht immer alles nur Fehler, sondern können auch Änderungswünsche an Darstellungen etc. sein, bei denen entschieden wurde, sie global umzusetzen.

Es ist leider auch nicht möglich, da immer eine "Einzelbewertung" durchzuführen, also die anderen Tickets, die dabei mit installiert würden, einzeln zu prüfen und für ok zu befinden, aktuell sind wir auf die Abnahme angewiesen.

Hat jemand eine gute Idee, wie man das ganze verbessern könnte?
 
Eigentlich dürfte es doch gar nicht passieren, dass etwas nicht freigegebenes in Hauptzweig und damit bei einem anderen Kunden im Testsystem landet, oder? Das sollte meiner Meinung nach nicht nach Fix und vor der Freigabe durch den Kunden im globalen Zweig landen. Nicht freigegeben heißt sogesehen ja auch nicht getestet und nicht getesteter Code hat nix im globalen Zweig verloren.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Burfi, Testa2014 und KillerCow
Also meiner Ansicht nach, gehört der Bugfix erst in den Master, wenn das vollständig getestet ist und vom Kunden die Freigabe kam.
Kunde A bekommt 2.4.a
Kunde B bekommt 2.4.b

Wenn die Freigabe kommt dann 2.4.x in 2.4.1, und beim nächsten dann 2.4.y in 2.4.2
 
  • Gefällt mir
Reaktionen: Grimba
Ich verstehe gerade auch nicht warum der Kunde bei euch überhaupt den globalen Zweig freigeben muss. Ihr habt selbst entschieden was in den globalen Teil rein kommt, dann sollte es auch kein Problem sein das einzuspielen, egal ob Kunde es freigibt oder nicht.
 
Ich stimme den anderen hier vollkommen zu. Nicht vollständig getesteter Code hat nichts im Master zu suchen.
Der darf erst nach eurer Freigabe zurück in den globalen Teil. Das heisst er muss auf allen Ebenen getestet sein.
In einem Fall, der Kundenspezifisch ist, also deinem Beispiel würde wir ein Release 2.4.1 direkt vom Bugfix Branch ableiten, nicht von Master.
Dieser Release wird nur bei Kunden A ausgerollt. Erst nach Freigabe wird dann der Bugfix Branch auch in den Master gemerged.
So kommen sich Kundenspezifische Bugfixes nicht in die Quere und der Master bleibt stabil.

Die negative Seite von diesem Ansatz ist natürlich, dass Master je nach Dauer der Tests beim Kunden nicht schnell genug die Änderungen bekommt und ihr somit mehr Merge Konflikte haben könntet, wenn dann endlich gemerged wird.
 
  • Gefällt mir
Reaktionen: BeBur
Ich muss Grimba zustimmen, im Master hat das nichts zu suchen.
Ich kenn allerdings auch genau das gleiche Problem, wir sind das wie folgt angegangen. Bei Paketen die in mehreren Systemen genutzt werden haben wir den Master + die jeweiligen System-Branches. Wenn Kunde A einen Fehler sieht wird dieser in einem a sub-branch behoben. Wenn die Entwicklung abgeschlossen ist geht es in den a-branch. Nach erfolgreichen Test geht es in den master und automatisch in b, c, d, ... Versionsnummern werden bei uns nur im master vergeben. Bei der nächsten Auslieferung für einen anderen Kunden bekommt er der Hinweis das mitzutesten, falls Fehlerhaft geht es wieder in die Runde bei Kunden x.

Die eigentlichen Kundenspezifischen Pakete sind von den übergreifenden komplett losgelöst und in einem einzelnen Repo.

@distrophik es gibt leider Prozesse die auf getestet pauken und wenn du dort irgendwas irgendwo reinschiebst kann das schnell nach hinten losgehen. Ja, das ist alles ein wenig oldschool und mit der modernen Welt der Entwicklung nicht direkt vereinbar. Wir können z.B. auch nicht einfach daher gehen und bei Kunden x alle Pakete aktualisieren, das macht man immer wenn sowieso an einem entsprechenden Paket bzw. einer Abhängigkeit gewerkelt wird. Somit ist es begründet und wird auch gleich getestet.
 
  • Gefällt mir
Reaktionen: BeBur
Natürlich müssen wir uns hier nicht darüber unterhalten, dass Bugfixes für Tippfehler in Strings o.ä. nicht das gesamte Prozedere durchlaufen müssen und man hier ggf. in beiderseitigem Einverständnis das ganze beschleunigt. Soviel ist klar.

Aber, auch wenn es wie Overhead aussieht, hier strikt vorzugehen und den Master auf Gedeih und Verderb sauber zu halten, so profitiert man im Nachhinein doch, denn auch vermeindlich kleine Fehler, die wie ein schneller Fix aussehen, führen mitunter zu Folgefehlern, die man so gar nicht vorausgesehen hat, z.B. weil man den gleichen Copy Paste Fehler auch woanders gemacht hat etc.

Auch bei uns ist es schon passiert, dass wir festgestellt haben, dass eine Funktion aufgrund eines Tippfehlers nie zur Ausführung kam. Die Funktion selbst an sich war zwar nicht kriegsentscheidend, so wirkte die Behebung des Tippfehlers wie ein schneller Bugfix und ein no Brainer. Allerdings zeigte sich dann im Nachhinein im Testbetrieb beim Kunden, dass jetzt, wo die Funktion ausgeführt wurde, im Nachgang Fehler entstanden, mit denen man vorher nicht gerechnet hatte. In eurem Fall würde sich Kunde B die gleiche Problematik einhandeln, wenn sich das bei euch so überschneidet.

Daher NIEMALS ungetesteten Code in den Master einchecken, und schon gar nicht diesen zum nächsten Kunden ableiten. Das ergibt doch eine katastrophale Kaskade. Dass hier A auf B warten muss, ist hier eigentlich noch das geringste Problem. Gerade wo hier die Rede von 20-30 solcher Fälle ist.

Stell dir vor du hast 10 Überschneidungen, und bei allen Bugfixes bei den anderen Kunden vorher ereignen sich Folgefehler im Testbetrieb. Dann bekommt Kunde 10 mit eurem Verfahren den gesamten Fehlercoktail von 9 anderen Kunden, der dann vielleicht gar nicht mehr gescheit zu lösen ist, da man bei jedem Kunden ja auch individuelle Begebenheiten seines Systems berücksichtigen muss. Hättet ihr stattdessen den Code vom Anfang genommen, so hättet ihr an dieser Stelle durch die Bugreports alles über den Code gewusst, bei jedem Kunden, und es hätte sich auf den Bugreport vom Kunden reduziert. Natürlich können die Bugs zusammenhängen, aber wengistens spielen keine neuen Seiteneffekte mit in die Problematik hinein.
 
Zuletzt bearbeitet:
@Grimba - Die Sache ist die, dass im Test- und im Livesystem ggf. die selben Versionen installiert sind. Es gibt also keinen Unterschied zwischen einem Testsystem-Release und einem Livesystem-Release.

Die Kunden-Projekte sind so eingestellt, dass sie sich automatisch die aktuellste Version vom globalen Teil 2.4 holen, wenn ein Release erstellt wird.

Der Bugfix wird also als Version 2.4.2 etc. in den globalen Teil eingefügt. Dann wird ein Release für Kunde B erstellt, dieses zieht sich dann die 2.4.2 vom globalen Teil und wird im Testsystem ausgerollt. Bei Abnahme im Testsystem wird eben dieses Release im Livesystem ausgerollt. Und da ist eben auch die Anpassung aus der 2.4.1 drin.

@5clowne - sowas wie 2.4a und 2.4b gibt es leider nicht. Es gibt die Version 2.4 und jeder Bugfix darauf zählt die Minor-Version danach hoch, also dann 2.4.1, 2.4.2, 2.4.3 usw.

@distrophik - Weil der Kunde eben absegnen soll, ob der Bugfix so gelöst wurde, wie er sich das vorstellt. In manchen Fällen kann das auch statt dem Kunden unsere interne QS-Abteilung sein, die aktuell erst mit allen Bugfixes durch sein müssen, bevor das installiert werden kann.

Ich verstehe eure Argumente prinzipiell, nur leider bin ich mir nicht sicher, ob wir unser System dahingehend einfach anpassen können. Ich muss dazu sagen, ich bin nur einfacher Entwickler, es liegt also nicht an meinem Unwillen, ich versuche nur, irgendwie das System zu verbessern.

Hat jemand mal eine Seite, auf der so ein Workflow schön verständlich skizziert ist? Anscheinend haben wir da ja ein recht grundlegendes Design-Problem, aber ich bin mir gerade nicht sicher, wie wir das mit unserem Workflow gescheit umstellen können.

Erschwerend kommt folgendes hinzu: Manche Kunden setzen den globalen Teil in Version 2.4 ein, manche in 2.5, manche in 2.6 usw.

Änderungen in 2.4 werden automatisch in die 2.5 und 2.6 gemerged usw.

Und ab und an wird eben ein neues Release vom globalen Teil erstellt (z. B. dann die 2.7), dieses wird immer vom Master-Branch des globalen Teils abgespalten und enthält dann Anpassungen am globalen Teil, die nicht auf den Releases (2.4 usw.) erstellt wurden, sondern im "Entwicklungs-Teil". Ausgerollt werden immer nur die Releases.

Ich habe versucht, diesen Ablauf mal grob zu skizzieren, ich hoffe, man versteht das einigermaßen, das ist jetzt einfach nur schnell hingemalt.
 

Anhänge

  • git_workflow.png
    git_workflow.png
    30,4 KB · Aufrufe: 281
Hallo,

nach meinem Verständnis habt ihr euch eine Conflicting Dependency Hell in eure Codeverwaltung gebastelt. Die Lösung dafür, das haben schlauere Leute schon alles einmal durchdacht, lautet Monorepo.
 
  • Gefällt mir
Reaktionen: Burfi
@ayngush - mit Mono-Repo würden wir aber die Möglichkeit verlieren, dass Kunde A das Release 2.4 und Kunde B Release 2.5 nutzt, oder? Und das ist aktuell leider zwingend notwendig.
 
Exterior schrieb:
Die Sache ist die, dass im Test- und im Livesystem ggf. die selben Versionen installiert sind. Es gibt also keinen Unterschied zwischen einem Testsystem-Release und einem Livesystem-Release.

Die Kunden-Projekte sind so eingestellt, dass sie sich automatisch die aktuellste Version vom globalen Teil 2.4 holen, wenn ein Release erstellt wird.

Der Bugfix wird also als Version 2.4.2 etc. in den globalen Teil eingefügt. Dann wird ein Release für Kunde B erstellt, dieses zieht sich dann die 2.4.2 vom globalen Teil und wird im Testsystem ausgerollt. Bei Abnahme im Testsystem wird eben dieses Release im Livesystem ausgerollt. Und da ist eben auch die Anpassung aus der 2.4.1 drin.
Ja, wenn das die Sache ist, dann läuft da aber was gewollt falsch.
Warum sollten Testsystem und Releasesystem auf der gleichen Versionsnummer sein? Sollte man nicht erst testen, und dann in Produktion gehen?
Umgekehrt: Warum macht ihr ein Release, wenn das noch gar nicht getestet wurde?
Es bleibt das Problem: IHR merged ungetesteten Code. Das lasst mal sein.
 
  • Gefällt mir
Reaktionen: Burfi
Wie ja schon angemerkt wurde: Euch fehlen da ein/zwei Zwischenschritte!
Das Beheben eines Fehlers oder Hinzufügen/Ändern eines Features in einem beliebigen Branch darf nicht automatisch dazu führen, dass die Änderungen dazu im Anschluss gleich in einem produktiven Branch landen.
Da braucht ihr einen Branch zum Sammeln aller Änderungen, z.B. einen "Staging-Branch" oder wie auch immer man es nennen möchte.
Zum Testen Liefert ihr dann einen Release Candidate für die bestimmte Version aus (also 2.4.1.rc oder was auch immer).
Nach Freigabe der Korrektur/des Features baut ihr dann die tatsächliche Version und verteilt sie an eure Kunden (also dann 2.4.1.0).

Das kann man dann, je nach Komplexität oder/und Umfang der einzelnen Versionen und Änderungen, noch weiter auffächern.
D.h. parallele Arbeiten an Version 3.0 bräuchte einen eigenen Staging-Branch, wenn die Features und Änderungen davon nicht in 2.x reinbluten sollen.
Dasselbe gilt natürlich für 2.5 und 2.4. usw.

Es ist dabei allerdings allgemein darauf zu achten, dass ihr einen guten Überblick darüber behaltet, welche spezifischen Änderungen die Änderungen eines anderen Themas voraussetzt.
Es entsteht dann natürlich zusätzliche Arbeit, da beim Mergen von so einer Änderung der Code angepasst werden muss.
 
Zuletzt bearbeitet: (Rechtschreibung)
Eigentlich wird erst im Testsystem ein neues Release ausgerollt und wenn das fertig getestet wurde, wird das Live ausgerollt. Aber ab dem Moment haben beide Systeme den selben Release-Stand. Wenn jetzt ein Bugfix kommt, wird der auch erst im Test- und danach im Livesystem installiert, aber er landet eben im selben Release-Branch, weil ab dem Livegang beide Systeme den selben Stand haben.

Und das Release wurde ja getestet. Das Problem sind ja die Bugfixes danach, die werden direkt auf diesen Releases durchgeführt.

Es bleibt das Problem: IHR merged ungetesteten Code. Das lasst mal sein.
Ich weiß, das ist ja das Problem. Ich weiß nur eben nicht, wie wir das gescheit umstellen können, ohne unseren kompletten Workflow von Grund auf zu überarbeiten.
 
Exterior schrieb:
@ayngush - mit Mono-Repo würden wir aber die Möglichkeit verlieren, dass Kunde A das Release 2.4 und Kunde B Release 2.5 nutzt, oder? Und das ist aktuell leider zwingend notwendig.
Ihr habt doch ein Repository pro Kunden, oder?
Jetzt nur noch schauen (= einen Workflow definieren und möglichst automatisieren), wie der von dir genannte "globale Projektteil" in entsprechender Versions-Abhängigkeit in das Kundenspezifische Monorepo wandert.
 
Exterior schrieb:
Ich habe versucht, diesen Ablauf mal grob zu skizzieren, ich hoffe, man versteht das einigermaßen, das ist jetzt einfach nur schnell hingemalt.
Ich bin mir halbwegs sicher, dass so ein Diagramm besser mal azyklisch ist.
Bevor du hier jetzt im Dialog von einmal schnell hingemalt zu zweimal schnell hingemalt gehst, setzt dich mal in Ruhe hin, denk nach und produziere einen definierten Zwischenstand.
 
Ich könnte mir folgende Verbesserung vorstellen:
-Features/Bugfixes werden mittels Feature Branches realisiert
Sind diese getestet, werden diese in den main branch gemergt
-Für ein kundenspezifisches Release, also eines, welches vom main Branch abweicht,
wird ein eigener Branch erstellt. Die für den Kunden vorgesehenen Features/Bugfixes
werden auf den kundenspezifischen Branch übertragen, z.B. mit git --squash merge
-Früher oder später sind alle Features/Bugfixes im main Branch. Spätestens
jetzt sollte man den kundenspezifischen Branch löschen. Je mehr kundenspezifische Branches,
desto mehr Verwaltungsoverhead.
 
Bin mir nicht sicher ob ich's richtig verstanden habe, aber würde es nicht genügen einen Branch für das Testsystem zu erstellen, in den ihr nach Belieben mergen, rebasen und cherry-picken könnt? Dieser Branch darf dann natürlich nirgendwo hin gemergt werden, alle Änderungen in Master müssen aus den Feature-Branches kommen. Der neue Branch sollte immer zeitnah auf Master resettet/rebaset werden wenn dort Änderungen erscheinen.
 
Zurück
Oben