Eine Alternative zu Branching könnte für euch auch "trunk-based" Development mit Feature-Toggles sein. Beim letzten Projekt/Kunden war dies das Modell der Wahl. Dort gab es ca. 30 Teams mit durchschnittlich 7 Personen pro Team und alle haben nach diesem Modell gearbeitet. Hier wurde dann auch wirklich ca. 2-5 Mal mit einem Service amselben Tag Live gegangen.
Das Modell sieht so aus:
- Es gibt keine Feature-Branches mehr, sondern nur noch persönliche "Staging"-Branches, die kurzzeitig hinter dem master liegen, wenn Unit- und Integrationstests auf den eingecheckten Änderungen laufen
- Nach Build- und Test-Erfolg wird der Stand auch sofort in den master Branch übernommen und danach automatisch auf Testsysteme/-deployments ausgerollt
Pro
- frühe Integration des Codes führt zu schnelleren Entwicklungszyklen und früher Fehlerbehebung
- Es werden immer integrierte Stände deployt, es gibt daher kein gegenseitiges Überspielen von Testständen auf Abnahmesystemen
- Entkopplung von fachlichem und technischem Livegang führt in beiden Fällen zu beschleunigter Auslieferung von Features
- Rollback-Prozesse, beim Integrieren von nicht funktionierenden Ständen, werden nahezu überflüssig
- Grundlage für A/B-Tests u.ä. (meistens direkt Unterstützt durch entsprechende Libraries oder Services)
Kontra
- Code wird komplexer (weil mit Feature-Toggles gearbeitet wird)
- Es werden mehr Tests benötigt, um alternierende Togglestände abzudecken
- Code enthält häufig ungenutzte Zweige, wenn Toggles nicht konsequent ausgebaut werden, oder es langalufende Experimente gibt
- Serviceüberspannende Features sind ggf. kompliziert umzusetzen
- Es wird zusätzlich eine Toggle-Library oder ein Toggle-Service benötigt
Feature-Toggles dienen hier nun generell dazu, den technischen Livegang (Code ist schonmal deployed) von einem fachlichen Livegang (User kann das Feature auch nutzen) zu trennen. Hierdurch können sehr schnell (Schalter umlegen) Änderungen getestet und wieder zurückgeschaltert werden.
Nach den eineinhalb Jahren, die ich da war, bin ich aktuell wieder in einem Projekt nach GitHub-Flow-Modell und es fühlt sich so uuuuuuunglaublich träge an.
EDIT: Und da ist dann ein "Release" immer eine riesengrosse Sache, wo sich alle zusammenfinden, mühsam über die JIRA Tickets gehen, die als für dieses "Release" abgeschlossen markiert wurden, und gucken, ob alles so gut ist. Das dauert manchmal wirklich den halben Tag, weil sich einfach über zwei oder drei Wochen sooo viel aufakkumuliert hat, dass nach der Zeit kaum noch jemand weiss, was da eigentlich gemacht wurde und ob sich das mit anderen Features/Fixes noch verträgt.
Beim trunk-based Ansatz mit mehreren Livegängen/Releasen pro Tag hatten zumindest wir im anderen Projekt diese Probleme nicht. Es gab dort einfach kein "zeremonielles" Release, wo man sich zusammenfindet und dann voller Erwartung auf einen Knopf drückt.

Stattdessen wurde halt einfach ständig released und es gab keine Release-Versionen. Weil zu jedem Zeitpunkt, wo man eine Änderung live stellt, waren die einzelnen Änderungen an sich immer sehr sehr klein.
Um sowas zu können, braucht man natürlich auch ein funktionierendes Continuous Deployment Modell. In unserem Falle damals war es ein Rolling Deployment, bei dem alte Instanzen batch-weise durch neue Serviceversionen ersetzt wurden und es niemals eine Downtime gab.
Das hätte auch sehr viel Geld gekostet, wenn es anders wäre (war der grösste deutsche Versandhändler).