Skip to content
This repository has been archived by the owner on Mar 26, 2024. It is now read-only.

[Draft] GIT Branching Development Vorschlag

Dennis Kobert edited this page Jul 25, 2019 · 2 revisions

GIT Branching/Development - Vorschlag

Nach einem kurzen Gespräch von Dennis und mir im Discord (siehe #frontend vom 24.7. 2019) haben wir beschlossen, dass ich mal einen Serviervorschlag für die Verwendung von Git schreibe.

Änderungen sind (sofern nicht z.B. "Repository" durch "Depot" ersetzt wird) explizit erwünscht, Feedback und Beschimpfungen werden via PM im Discord (oder hier) natürlich dankend angenommen. Des weiteren erhebt das Zeug hier natürlich keinen Anspruch auf Vollständigkeit.

tl;dr

Ich habe versucht, meine Gedankengänge einigermaßen klar zu machen. Hier die Kurzzusammenfassung:

  • Ein Monorepo bleibt, wir sollten uns aber überlegen, wie wir am besten die Animationen hosten
  • Features werden auf dedizierten Branches entwickelt und auf eine dev Branch gemerged, die regelmässig auf master gemerged wird. Änderungen werden über Pull Requests reviewed und von anderen getestet.
  • Aufgaben werden in einem Board getrackt, damit klar ist, woran aktuell gearbeitet wird und was aussteht.

Wozu?

Auch wenn ich durch zeitliche Constraints in den letzten Wochen nicht viel beitragen konnte, habe ich relativ regelmässig die Änderungen im Repository beobachtet und dabei sind mir u.a. folgende Punkte aufgefallen (in den folgenden Ansätzen werde ich meine Verbesserungsvorschläge genauer beschreiben):

  • Es wurde sehr autark auf verschiedenen Branches gearbeitet (siehe ratatosk und wasm), was zu einer starken Divergenz der Branches geführt hat. Diese erhöht das Risiko, dass eine Zusammenführung in ein releasefähiges Paket auf master zu Komplikationen führt. Noch dazu wurde regelmässig gemerged, was insbesondere bei Feature- bzw. Topicbranches zu einer vermeidbaren Verkomplikation der Historie führte.

  • Durch regelmässiges Pushen direkt auf die Branches ohne Reviewprozess kann es auf Dauer zu Silos führen, also jeder ist auf seine Lösungen spezialisiert, allerdings fehlt u.U. das Implementierungswissen (das Design ist nicht betroffen, da dies gemeinsam ausgearbeitet wird) über andere Komponenten.

Ich habe diese Beobachtungen versucht, einigermaßen allgemein zu halten, weitere Details kommen.

Struktur des Repositories

Ich empfehle, an der Struktur eines sog. Monorepos, also einem Repository, das schlicht alle Sourcen enthält, festzuhalten. Das Splitten in kleine Repos sorgt oft dafür, dass vertikale Änderungen an der Codebase zu einem deutlichen Mehraufwand führen, da sowohl lokal alle Repositories adäquat organisiert werden müssen und der Review/Merge Prozess an mehreren Stellen durchlaufen werden muss, was insbesondere bei Änderungen problematisch werden kann, die Inkompatibilitäten in internen APIs hervorrufen.

Die einzige Frage ist, wie mit dem animation-Branch passiert, da dieser (zumindest zum aktuellen Zeitpunkt) weitesgehend unabhängig von den restlichen Komponenten gepflegt wird. Grundsätzlich wären folgende Ansätze möglich:

  • Auslagerung der Sourcen in ein zweites Repo, das über Git Subtrees inkludiert wird. Auf diese Weise besitzen alle Entwickler den gleichen Stand und es kann komfortabel via git subtree pull geupdated werden. (Wichtig: es sollte nach Möglichkeit die Verwendung von git submodule … vermieden werden!).

    In diesem Fall wäre eine Ausnahme der Monorepo-Empfehlung durchaus möglich, allerdings ist die Frage, ob in Zukunft durch viele Änderungen in den Animationen eine direkte Einbettung in das Hauptrepo nicht besser wäre.

  • Push-Access für animation/ erlauben: da Animationen in #grafik-design im Discord behandelt werden, könnte auf diese Weise die in diesem Fall obsolete Bürokratie durch Review-Prozesse vermieden werden.

  • Einbettung in den Review-Prozess (siehe Contributions): in diesem Fall würde animations/ wie jede andere Änderung behandelt werden.

Hinweis: dies waren nur 3 spontane Ideen von mir, es ist auf alle Fälle sinnvoll, das gemeinsam zu klären.

Zu guter Letzt sei noch auf die Existenz von sog. Protected Branches hingewiesen, die explizit Dinge wie ungewollte force-pushes auf Branches verhindern. Des weiteren kann auf diese Weise sichergestellt, dass z.B. keine nicht reviewten Changes übernommen werden.

Im Allgemeinen würde bei der Entwicklung die Verwendung von Featurebranches setzen. Wie bereits angesprochen, haben der Ansatz mit einer Branch pro Directory den Nachteil, dass Wissen nicht entsprechend verteilt ist und z.B. Tests, ob es einen allgemein funktionierenden Zustand gibt, erschwert, da die meist hohe Divergenz zwischen den Branches zu Konflikten führt, insbesondere, wenn Crates geteilt werden.

Ein Beispiel wäre folgendes Modell:

Git Branches

Die reine draw.io Fassung kann unter wolke.mbosch.me runtergeladen werden.

Zur Erklärung:

  • feature_* ist eine Branch, auf der aktiv von einem oder mehreren an einem Task gearbeitet werden kann. Diese Branches sollten nicht protected sein, forcierte Pushes sind explizit in Ordnung. Sobald ein Feature durch ist, sollte ein Pull Request auf dev eröffnet werden. Weitere Details zur Arbeit finden sich im nächsten Absatz.

  • dev (Protected) ist eine Branch mit einem möglichst aktuellem Stand, mit dem alle arbeiten sollten, um auf einem einheitlichen Stand zu sein. Standardmässig sollten alle Pull Requests hierhin geöffnet werden.

  • master (Protected) ist eine Branch mit einer stabilen(tm) Fassung des Projektes, die theoretisch immer releasefähig sein soll. Mit anderen Worten: wenn Features ausreichend getestet wurden, können diese auf master gemerged werden. Zum aktuellen Zeitpunkt sollte "releasefähig" bedeuten, dass die aktuellen in Komponenten in einer Alpha-Fassung veröffentlich werden können, ohne ein funktionsfähiges Paket bereitstellen zu müssen, was zu einem entsprechend frühen Entwicklungsstadium nur bedingt sinnvoll ist.

Contributions

Wenn an einem neuen Feature bzw. einer neuen Aufgabe gearbeitet wird, kann von einer aktuellen dev Branch aus eine feature_* Branch ausgecheckt werden mit git checkout -b feature_foo_bar. Wenn diese Branch einen aktuelleren Stand von dev benötigt, kann diese via git rebase dev aktualisiert werden.

Im Gegensatz zum merge aktualisiert ein rebase die aktuelle Branch auf den Stand der zu rebasenden Branch (hier: dev) und versucht dann, die auf der Branch getätigten Commits vorne dran zu hängen. Dadurch wird die Historie verwendet, wodurch ein force-push (git push -f) notwendig wird, weshalb dies nur auf Feature Branches möglich sein sollte. Dadurch ergeben sich folgende Vorteile:

  • Bei älteren Branches gibt es keine Vermischung zwischen "frischen" Commits von dev und auf der Feature Branch getätigten Commits, was z.B. ein Bearbeiten der Commits (zum Ändern der Commit Message oder dem sog. squashen mehrerer Commits) vor dem finalen Merge erheblich vereinfacht.

  • Durch Rebasen erkennt man einfacher, was auf einer Branch selber befindlich ist und was von dev neu dazugeholt wurde. Dadurch werden auch Merge Commits vermieden, die bei regelmässigen Aktualisierungen der Feature Branch zu einer starken Verkomplikation des graphischen Trees des Logs führt und die Nachvollziehbarkeit der Historie u.U. weiter erschwert.

Hinweis: wenn mehrere Leute auf einer Branch arbeiten, sollte bei Force-Pushes vorgewarnt werden. Der zweite Entwickler sollte dann seine Änderungen via git stash zwischenspeichern, die neuen Änderungen via git pull --rebase ziehen und seine lokalen Änderungen dann darauf anwenden (git stash pop).

Sobald ein Feature bzw. eine Aufgabe fertig ist, kann ein PR gestellt werden (ggf. auch schon früher, um früh Feedback einzuholen, in diesem Fall sollte der PR allerdings als "Draft" deklariert werden). Um mögliche Fehlerquellen auszuschließen, sollten nur auf dem Jenkins laufende Änderungen gemerged werden, die von mind. einer Person approved wurden. (Derartige Regelungen können in den Einstellungen des Repos auf GitHub auch explizit festgelegt werden).

Um die Zuweisung von Reviewern zu vereinfachen, kann z.B. mit .github/CODEOWNERS gearbeitet werden.

Sobald ein Themenblock auf dev fertiggestellt wurde, kann nach einem ACK aller Entwickler einer die Änderungen via git merge --no-ff (um Sicherzustellen, dass zu Dokumentationszwecken ein Merge-Commit entsteht) auf master gemerged werden und ein Release vorbereitet werden.

Zu diskutieren ist noch, wie man mit "Hotfixes", z.B. für den master umgeht (z.B. via cherry-picks).

Organisation

Es empfiehlt sich außerdem, zumindest ein grundlegendes Tracking von Aufgaben einzuführen, damit klar ist, woran aktuell von wem gearbeitet wird, was auch die Kommunikation im Discord vereinfacht.

Neben Pull Requests für Änderungen, können Tasks als Issues angelegt werden mit einer groben Beschreibung. Zum Tracking können ein oder mehrere Boards (also ein Board für alles oder z.B. ein Board pro Umgebung wie wasm, engine etc.) verwendet werden mit folgenden Spalten:

  • Pending: alle aktuell ausstehenden Aufgaben. Ggf. können hier auch mehrere Spalten zur genaueren Differenzierung genutzt werden.

  • In Progress: Aufgaben, an denen aktuell aktiv gearbeitet wird.

  • In Review: Änderungen, die einen Pull Request besitzen, bei denen ein Review im Gange ist.

  • Done: Änderungen, die auf dev gemerged wurden und entsprechend als erledigt anzusehen sind. Commits sollten das entsprechende Issue dann mit Resolves #<ticket-num> in der Commit Message schließen.

  • (optional) Stable: Änderungen, die auf master gemerged wurden und damit als stabil angesehen werden.

Navigation

Brainstorming:
      Sessions Liste 📃
      Letzte Session ◀️
      Nächste Session ▶️
      Last Design-Session 👈
      Next Design-Session 👉
      Dunkle Seite 🌈
Design:
      Sound 🎧
      Grafikdesign 🤺
      Animationen 🎞️
      Gamedesign 📝
Programmierung:
      Gamelogik ⚙️
      Frontend 👾
      Backend 🗄️
Spielprotokoll 🧻

Clone this wiki locally