-
Notifications
You must be signed in to change notification settings - Fork 1
[Draft] 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.
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 aufmaster
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.
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
undwasm
), was zu einer starken Divergenz der Branches geführt hat. Diese erhöht das Risiko, dass eine Zusammenführung in ein releasefähiges Paket aufmaster
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.
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 vongit 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ürdeanimations/
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:
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 aufdev
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 aufmaster
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.
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).
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 aufdev
gemerged wurden und entsprechend als erledigt anzusehen sind. Commits sollten das entsprechende Issue dann mitResolves #<ticket-num>
in der Commit Message schließen. -
(optional)
Stable
: Änderungen, die aufmaster
gemerged wurden und damit als stabil angesehen werden.
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 🧻