Eine von mir lange gehaltene Überzeugung, die ich hier endlich aufschreiben werde: Manchmal profitieren Softwareprojekte davon, wenn die Entwicklungsarbeit nicht per Pullrequests eingesendet wird, sondern wenn die Entwickler direkt den Masterbranch ändern. Es erleichtert das Testen und ermächtigt Entwickler.
Erklärungen vorab
Programmierern dürfte der Großteil in diesem Abschnitt klar sein, aber um so viele mitzunehmen wie möglich und Missverständnisse zu vermeiden:
Bei der Arbeit an Software wird inzwischen fast immer Git als Versionsverwaltung eingesetzt. Im üblichen und meiner Erfahrung nach von Firmen ausschließlich genutzten Nutzungsmodus erstellen Entwickler für ihre Aufgaben immer neue Kopien als Grundlage für ihre Änderungen (Branches, dann Featurebranches genannt), die sie dann als Pullrequest an das Projekt schicken. Ein anderer Entwickler prüft die Änderungen in einem mehr oder weniger ausgiebigen Codereview, danach werden sie dem gemeinsamen Entwicklungsbranch hinzugefügt. Wenn zwischendurch andere Codestellen verändert wurden kann oft genug Git die Änderungen zusammenbringen, gibt es aber einen direkten Konflikt müssen die Entwickler diesen manuell auflösen (und entsprechend testen). Diese Nutzungsweise gibt es in mehreren Varianten, eine davon wird Gitflow genannt, nutzt permanent mehrere Branches (mindestens master und dev) und war lange ziemlich populär.
Beim kürzlich wiederaufgekommenen Trunk-based development – vom Namen her ein Verweis auf Entwicklungsweisen vor Git, so war Trunk der Name für den Hauptbranch beim alten Versionsverwaltungssystem CVS – entfallen laut der verlinkten Definition die mehreren Branches, alles liefe schnell im Master zusammen. Aber es gäbe so wie sich das dort liest immer noch die PRs. Laut anderen Definitionen entfallen die ganz, senden Entwickler ihre Änderungen direkt in den gemeinsamen Masterbranch. Und dann sind wir bei meinem Thema.
Vorteile davon, ohne PRs zu arbeiten
Es sind dabei vor allem zwei Punkte, die ich beim direkten Ändern des Masterbranches positiv sehe.
Und zwar primär (und nur tautologisch klingend), dass Änderungen direkt im Masterbranch landen. Das macht sie sichtbarer: Denn anstatt in einem eigenen Branch auf Reviewer und Tester zu warten, wird in manchen Projekten der neue Code im Masterbranch viel eher wahrgenommen. Nämlich immer dann, wenn einzelne Nutzer nicht auf Releases warten, sondern den Code direkt nutzen. Das machen zum Beispiel bei Serendipity ein paar Nutzer mit ihren Blogs. Die akademische Literatur zu FOSS würde sie als Nutzerchampions bezeichnen: Als Nutzer, deren Engagement über das normale Maß hinausgeht und die so die Entwicklung beeinflussen, ohne notwendigerweise selbst Code zu schreiben. Der Masterbranch (aber eben nur der) wird durch sie ausgiebig getestet und Probleme an die Entwickler gemeldet.
Genauso stolpern auch andere Entwickler direkt über den neuen Code, wenn er direkt im Master landet. Es besteht kaum mehr die Gefahr, dass Arbeit gedoppelt wird oder zwei Entwickler in ihren eigenen Branches inkompatible Systeme bauen. Auch Mergekonflikte werden seltener.
Dieser Vorteil wird nochmal wichtiger, wenn PRs lange liegenbleiben können. Wieder Serendipity als Beispiel, das jQuery-Upgrade wäre garantiert nicht fünf Jahre liegengeblieben wenn sein Ansatz schnell im Master gelandet wäre. Wir hätten so bemerkt, dass die gröbsten vermeintlichen Inkompatibilitäten gar nicht an der Javascriptseite hingen (zumindest ist das mein derzeitiger Stand). Das ist übrigens kein Problem nur mit freien Projekten, auch in Firmen mit proprietärer Software habe ich mehrfach erlebt, dass PRs lange liegenbleiben und teils sogar verrotten, also am Ende nicht mehr gebraucht werden konnten weil sich um sie herum zu viel geändert hatte.
Zweitens ist das direkte Ändernkönnen des Masterbranches eine Ermächtigung des Entwicklers. Es bedeutet, dass das Projekt zumindest soweit auch ihm gehört, dass er nicht jede Änderung von anderen absegnen lassen muss. Wenn mal etwas nicht passt, kann das später immer noch geändert werden – bei einer vertrauensvollen Zusammenarbeit eines fähigen Teams ist das auch für niemanden ein Problem. Mit PRs als notwendigen Zwischenschritt ist stattdessen immer die Zustimmung eines Reviewers notwendig (wobei diese Anforderung formell oder informell sein kann), der einzelne Entwickler daher immer sehr viel abhängiger von anderen. Keine gute Voraussetzung, um sich als (Mit-)Entscheider zu fühlen.
Diese Abhängigkeit ist natürlich wieder besonders problematisch, wenn PRs liegenbleiben können. Das muss ja – anders als beim Beispiel mit jQuery oben – gar nicht an konstatierten Problemen liegen, sondern in vielen FOSS-Projekten ist es schlicht Zeitmangel. Und selten ist ein eigener PR den anderen genau so wichtig wie einem selbst. Dann wird die Abhängigkeit von den anderen zu einer frustrierenden Blockade der Entwicklungsarbeit.
Tatsächlich würde (und tue) ich mischen
Pragmatisch ist das Mischen von beiden Ansätzen, und ich fahre damit schon eine Weile meiner Wahrnehmung nach ganz gut. Während das komplizierte Branchmanagement von Gitflow generell abzulehnen ist, haben Pullrequests klare Vorteile. Und die kann man auch dann nutzen, wenn man sonst direkt in den Masterbranch pusht: Immer, wenn Änderungen Abstimmungsbedarf haben, macht man dann eben doch einen PR auf. Zum Beispiel wenn die zu nutzende Version der Programmiersprache sich ändert und dafür große Codeänderungen nötig sind. Sowas landet in einem PR, damit die anderen Entwickler draufschauen und bei der Migration helfen können.
Und wenn mal solch ein PR zu lange braucht und das die eigene Motivation zu ersticken droht? Dann drückt man eben selbst auf den Mergebutton, akzeptiert den eigenen PR auf eigene Kappe. Die anderen hatten dann wenigstens eine Chance gehabt, vorher Rückmeldung zu geben. Sollten in den späteren Tests die Änderungen Probleme machen kann man so oder so immer noch entscheiden, ob an ihnen weitergefeilt werden sollte oder ob sie zurückzunehmen sind.
Klar: Wenn ein Entwickler von außerhalb des Projekts Änderungen einsenden will – wie es bei FOSS-Projekten hoffentlich häufig geschieht – dann wird es völlig unabhängig von allen Überlegungen der internen Arbeit ein PR, der zu reviewen ist. Will man auch in dem Szenario trotzdem PRs soweit möglich vermeiden kann man so jemanden ja schnell ins eigene Team einladen, das mit dem direkten Zugriff auf den Masterbranch entwickelt sich dann meist nach etwas Zögern ganz natürlich.
Das ganze ist ein Balanceakt zwischen Qualität und Entwicklungsgeschwindigkeit, Motivation des Einzelnen und Einflussnahmemöglichkeiten der Gruppe. Man kann damit auf die Nase fallen, man kann aber auch schmerzhafte Blockaden lösen und Projekte besser am Laufen halten. Wichtig ist bei solchen Freiheiten besonders, dass das Entwicklungsteam sich ziemlich vertraut.
Auch ist es wichtig, dass keiner im Team ist, der vor sich hinstümpert und dauernd unlesbaren Code direkt in den Master pusht, am besten noch ohne erkennbare Commitstruktur. Solches Verhalten würde den Ansatz natürlich direkt kaputtmachen und dann braucht es unbedingt die Struktur von PRs und Codereviews, um das Projekt zu schützen. Wobei solche Entwickler dann meiner Erfahrung nach auch mit Codereviews nicht zu bändigen sind, aber das ist ein Thema für sich.
Eure Erfahrungen würden mich interessieren: Habt ihr selbst schon in Teamprojekten ohne PRs gearbeitet, und hat es gut funktioniert?