# Arbeit mit git im WiTTFind Projekt Jede Mitarbeit, jedes Programmieren im WiTTFind Projekt muss über das gitlab koordiniert und dort abgelegt werden. Nutzer unseres gits bekommen einen Zugang vom Sysadmin freigeschaltet. ## Einloggen in das gitlab (mit Passwort und mit ssh-key) Damit man optimal mit unserem gitlab arbeiten kann, muss man sich einen SSH-KEY zwischen dem eigenen Rechner und unserem GIT-LAB Server einrichten. Wie das geht findet Ihr * hier: http://doc.gitlab.com/ce/ssh/README.html und * hier: https://gitlab.cis.uni-muenchen.de/help/ssh/README#generating-a-new-ssh-key-pair Der SSH-Key muss dann in ihrem Benutzerprofil für jeden Rechner, mit dem Sie am gitlab arbeiten eingetragen werden: * siehe hier: https://gitlab.cis.uni-muenchen.de/profile/keys ## Git von der Kommandozeile Wir arbeiten im Allgemeinen mit dem git von der Kommandozeile aus, nur bei kleinen Änderungen verwenden wir die Browser gitlab Funktionen. ## Git Command-Line tool für Windows Ein sehr gutes Command-Line Tool für Windows gibt es hier: https://git-scm.com/download/win ## Kommentare und Readme Files im Markdown Format Erläuterungsfiles, Notizen und Bemerkungen im gitrepository bitte im Markdown-Format schreiben (Extension .md). Dann kann man die Texte etwas formatieren und das gitlab zeigt es auch formatiert an. * siehe: https://guides.github.com/features/mastering-markdown/ ## Hier ein Artikel zu git bei Heise.de https://www.heise.de/download/product/git-57506 ## Weitere Bemerkungen zu git: Hier sind zwei Foliensätze von Florian Fink, auf denen Details von git erklärt werden. * Foliensatz 1 : https://www.cis.uni-muenchen.de/~finkf/ss15/slides4.pdf * Foliensatz 2 : https://www.cis.uni-muenchen.de/~finkf/ss15/slides5.pdf * Für einen schnellen Einstieg bzw. eine Wiederholung der wichtigsten Feature empfehlen wir diesen [Link](https://rogerdudler.github.io/git-guide/index.de.html) # Branching model In unserem Projekt wird das in der Praxis bewährte git *branching model* von [hier](http://nvie.com/posts/a-successful-git-branching-model) in `wittfind-web` und in `wittfind-data` verwendet. Jede Arbeit in unserem gitlab muss sich auf ein Issue beziehen. Issues werden von der WiTTFind Oberfläche über die FeedbackApp erstellt (siehe nächstes Kapitel) ## Anlegen eines Issues über die FeedbackApp Mit Feedbackapp von wiTTFind können sie ein Issue erzeugen: hier : http://wittfind.cis.lmu.de/?feedback. In dem Issue, das sie nun anlegen, soll genau beschrieben werden, was bearbeitet wird. Die Feedback-App erstellt gitlab automatisch ein Issue in unserem gitlab mit einer eindeutigen Nummer (z.B. 447) Hier finden Sie einen Überblick über alle Issues der WAST-Tools: [hier](https://gitlab.cis.uni-muenchen.de/wast/wittgenstein-issues) ## Ermitteln eines branch Namen Mit der Issuenummer, das die Feedbackapp ins gitlab geschrieben hat (z.B. 447) muss man einen neuen Branch anlegen. Der Name des branches soll sich an folgende Syntax halten: `feature/XXXX-issue-447` unter XXX bitte einen "klingenden" Namen eintragen, der das Thema dieses Issues wiederspiegelt. ## Abzweigen vom Master-branch in den neuen branch Im repository gibt einen `master` Branch. * zuerst auf Branch master (normalerweise ist das der Default) + `git checkout master` * neuen Branch anlegen und abzweigen vom Branch master (normalerweise ist das der Default) + `git checkout -b feature/XXXX-issue-447` ## nun beginnt die Arbeit unter diesem branch .... Alle Veränderungen werden geloggt und können mit `git status` angezeigt werden. Wenn Sie mit Ihrer Arbeit an einem Punkt angekommen sind, wo sie Unterstützung brauchen, denn können Sie ihren Branch auch pushen und Fragen in der comment-Message stellen. ## Fragen an die Mitprogrammierer Wenn Sie während der Arbeit Fragen an die Mitprogrammierer oder den Projektmanager haben, dann können Sie das als comment-Message in ihrem Issue stellen. Schicken Sie mit ihrer Message eventuell einen screen-shot mit. Schicken Sie aber keine Programm oder Datendateien mit ihrer gitlab-Message. Nutzen sie ihren Branch um Dateien mitzuschicken. ## Wenn Sie mit der Arbeit fertig sind, dann gilt es die Datei in GIT Repository zu pushen Es ist ganz wichtig, dass beim * zuerst die zu pushenden Dateien adden (Wildcards sind zugelassen) + `git add file` + `git add **` läuft rekursiv durch alle Verzeichnisse und "added" alle Files * Datei lokal commiten + `git commit -m "Message"` * Datei vom feature Branch nach REMOTE pushen + `git push -u origin feature/XXXX-issue-447` ## Merge Request Der `master` Zweig aller Repositories ist per default nur für die `owner`des Repository freigegeben. So muss jeder andere einen merge Request nach `master` stellen. In der Merge Request Beschreibung sollten unbedingt folgende Punkte berücksichtigt werden: * Eine klare Beschreibung, was der Merge Request genau implementiert. * Ein Verweis auf das Ursprungsissue (falls vorhanden) sollte gesetzt werden. Um auf das `WAST/wittgenstein-issues` Repository zu verweisen, muss die Cross-Projekt-Referenznummer verwendet werden, beispielsweise: ```bash wast/wittgenstein-issues#508 ``` Dieser entsprechender Verweis findet sich auf der jeweiligen Issuebeschreibungsseite. * Um den bestreffenden Issue oder auch mehrere Issues automatisch nach Annahme des Merge Requests zu schließen, kann das *issue closing pattern* verwendet werden: ```bash Closes wast/wittgenstein-issues#508 Fixes wast/wittgenstein-issues#508 and wast/wittgenstein-issues#509 Closes wast/wittgenstein-issues#508,wast/wittgenstein-issues#509 and wast/wittgenstein-issues#510 ``` Nachdem der Merge Request angenommen wurde, werden die im Beschreibungstext referierten Issues automatisch geschlossen. Dazu wurde die GitLab Instanz speziell angepasst : **sofortiger Deploy auf dev.wittfind.cis.uni-muenchen.de** ### Probleme bei Merge Requests mit GitLab: Manuelles Mergen Wenn das GitLab Probleme bei Automatischen MERGE-Befehlen hat, dann muss das Mergen Manuell mit git-Befehlen realisiert werden. Der einzige benötigte git-Befehl dafür ist `git merge `. Wenn also Branch `feature/issue-1` nach `development` gemerged werden soll, schaut es folgendermaßen aus: 1. Zielbranch (hier `development`) auschecken: `git checkout development` 2. Merge vollziehen: `git merge --no-ff feature/issue-1` Eventuell entstehen hier Mergekonflikte - git erklärt hier aber genau, was zu tun ist. Falls ich den Source-Branch noch remote löschen möchte, geht das über `git push :` - besonders wichtig ist hierbei der Doppelpunkt. # Continous Integration Das gitlab, mit dem die WAST-tools gemanaged werden, arbeitet mit der Technik: Continuous Integration, siehe dazu auch [hier](https://docs.gitlab.com/ee/ci/quick_start/README.html). Repositories, bei denen der gitlab ci Runner aktiviert ist und eine `gitlab-ci.yml` Datei im Root-Verzeichnis des Repositories existiert, starten bei jedem push eine sogenannte "Continous Integration" (CI). Man nennt dies ausrollen des branches. Die "CI" arbeitet die Befehle in der yaml Datei `gitlab-ci.yml`ab. Alle Befehle, die zum "Ausrollen" eines pushes innerhalb eines Repositories notwendig sind werden von den Programmierern des Repositories in der yaml Datei `gitlab-ci.yml`definiert. Der Anweisungen in der yaml Script-Datei orientieren sich an den üblichen Techniken der UNIX-Shell Programmierungen und Makefiles, wurden aber gegenüber der UNIX-Shellprogrammierung und Makefiles um zahlreiche Erweiterungen ergänzt. Das zentrale Konzept in einer gitlab-ci sind sogenannte `jobs`, die in `pipelines` zusammengefasst werden. `jobs` erinnern an die targets in Makefiles. Es gibt vordefinierte jobs, wie `before-script:` (hier werden z.B. Environmenvariablen definiert, die für die Ausführung der Befehle notwendig sind). Jeder Job kann Konfigutations-Parameter definieren, die genau festlegen, wann und in welchem Kontext die nachfolgenden Befehle ausgeführt werden. Ein spezieller Job sind die sogenannten `stages` die unterschiedliche Integrationsebenen definieren, an denen der ci-Runner die Anweisungen abareiten soll. Sollte in einem "stage" ein Fehler passieren, bricht der ci-Runner die Arbeit ab. Im allgemeinen verwendet man die drei `stages` * build * check * deploy Jeder Job legt kann in seinen Konfigurationsparameter `stages` festlegen, bei welcher Integrationsebene er aktiv werden soll. Ähnlich zu Makfiles werden im yaml-skript auch Dependencies definiert, die auf andere jobs verweisen, die Befehlsfolgen definieren, die abzuarbeiten sind. Soll ein Job in einer yaml Datei auskommentiert werden, setzt man dem Jobnamen einen Punkt voran. Es wird dann ein `hidden-job` definiert. `Hidden-Jobs` können aber auch als Template-Jobs verwendet werden, die später an beliebiger Stelle eines anderen Jobs eingeführt werden. Den `hidden-jobs` wird ein Anchornamen nachgesetzt, die Einfügestelle in einem andern Job wird mit einer "merge-Anweisung" definiert. ``` .my_template_test: &test script: -make test testing: <<: *test script: - make deploy ``` ## wichtige ci Konfigurationsparameter Ein sehr wichtiger Konfigurationsparameter der ci-integration ist `only `. Er legt fest, bei welchem `branchname` der job aktiviert werden soll. z.B. `only master` : Nur wenn was auf den `master` branch gepushed wird, werden die Anweisungen des jobs ausgeführt. ## Probleme mit der ci im Team Es stellt ein großes Problem in der Teamarbeit dar, wenn **jeder** push in ein Repository sofort ausgerollt wird, was ja das Default-verhalten der ci-Technik vorschreibt. Im WAST gitlab wird jeder push * nach `master` auf unserem Produktion-Server (cast1) ausgerollt: : sichtbar unter `wittfind.cis.lmu.de` * alle anderen pushes werden auf dem Testing-Server (cast2) ausgerollt: sichtbar unter `dev.wittfind.cis.lmu.de` **ACHTUNG**: Wenn die Teamprogrammierer sich nicht absprechen, oder auf unterschiedlichen Branches unterschiedliche Arbeiten ausführen, überlagert jeder push in ein Repository sofort den vorherigen push. Programmierer sind überrascht, wenn plötzlich die vorherige Arbeit der Kollegen auf `dev.wittfind.cis.lmu.de` *verschwunden* ist. So muss sich das Team absprechen * was in welchem branch gepushed wird * oder einen gemeinsamen branch definieren z.B. `development` an dem zentral gearbeitet wird und in den die branches, sobald ein erfolgreicher Zwischenschritt programmiert ist, gemerged werden. Durch gezieltes Starten eines vorherigen runner-Laufes könnte aber jederzeit ein beliebiger push im Repository wieder aktiviert werden. Es gäbe mit dem Parameter `except` die Möglichkeit branches vom Ausrollen auszuschliessen. # Für gitlab Adminstratoren ## Release Um ein Release, beispielsweise für den Meilenstein *15.7* vorzubereiten, sind folgende Schritt notwendig: * setzen in den `master` Zweig, + `git checkout master` + `git push origin master` * Der Release-Zweig mit dem Namen `release/15.7` wird auf dem `master` Zweig erstellt: + `git checkout master` + `git checkout -b release/15.7 master` * Danach wird die Versionsangabe in `config.default` auf `"Version": "15.7"` angehoben * Die geänderte Version von `config.default` wird dann dem Release-Zweig hinzugefügt: + `git add config.default` + `git commit -m "Bump version to 15.7"` * Danach gibt es einen `--no-ff` Merge von `release/15.7` mit dem `master` Zweig (das geht bequem per GitLab Oberfläche) oder: + `git checkout master` + `git merge --no-ff release/15.7` * Nach diesem Merge wird der Zweig `release/15.7` ebenfalls auch noch in den `development` gemergt, damit `master` und `development` wieder gleich sind. Das geht ebenfalls per GitLab Oberfläche oder: + `git checkout development` + `git merge --no-ff release/15.7` * Zum Schluss wird ein Tag mit dem Namen *15.7* erstellt und als Beschreibung *version 15.7* vergeben: + `git checkout master` + `git tag -a 15.7 -m "version 15.7"` Somit ist der Meilenstein *15.7* erfolgreich nach unserem *branching model* publiziert worden! ## Hotfix Um einen Hotfix-Zweig in `master` zu integrieren, geht man ähnlich wie beim *Release* vor: * Der Hotfix-Zweig namens `hotfix/issue-123` wird vom `master` Zweig weggezweigt: + `git checkout master` + `git checkout -b hotfix/issue-123 master` * Dort werden dann alle Änderungen für den Fix vorgenommen und zu dem Zweig hinzugefügt * Danach wird der `hotfix/issue-123` Zweig in `master` mittels `--no-ff` gemergt: + `git checkout master` + `git merge --no-ff hotfix/issue-123` * Zum Schluss muss die Versionsangabe erhöht werden - beispielsweise von *15.7* auf nun *15.7.1*. Die Nummer am Ende wird für jeden Hotfix dementsprechend erhöht. Dazu wird exakt so vorgegangen wie in *Release* beschrieben ## Submodule ### Einrichten eines Submoduls: Wenn Repositories die Programme/Daten aus anderen Repositories verwenden sollen, dann können sie über "submodule" in das Repository eingebunden werden. Dazu sind zwei Befehle im geclonten Repository notwendig: Addiert den masterbranch des Repository (wichtig ist, dass sie den branch explizit angeben!!) + `git submodule add -b master git@gitlab.cis.uni-muenchen.de:wast/tokingtagging.git` Initialisiert die git Configuration: + `git submodule init` Commit und pushen + `git commit -m "submodule init" ` + `git push origin master` ### Entfernen eines Submodules: + `git submodule deinit -f — tokingtagging` + `rm -rf .git/modules/tokingtagging` + `git rm --cached tokingtagging` ## git lsf Wenn größere Binärdaten in einem Repository gespeichert werden sollen, dann sollten diese Binärdaten nicht als reguläre Files im Repository gespeichert werden, sondern als git-lfs (git-large-file) File. see: https://git-lfs.github.com/ + `git lfs install` + `git lfs track export-data/**` + `rm -rf .git/modules/tokingtagging` + `git rm --cached tokingtagging` # Meilensteine Zur besseren Versionierung und zum Sammeln bestimmter Aufgaben für einen bestimmen Termin, werden Meilensteinen mit dem Namensschema `.` angelegt. Ein Milestone definiert einen Zeitraum, in dem er bearbeitet werden muss und ihm werden Issues zugeordnet, die für seine erfolgreichen Abschluss erledigt sein müsssen. Damit Issues über mehrere Repositories verteilt einem Milestone zugewiesen werden können, empfielt es sich einen "Guppen-Milestone" anzulegen. (in neuen gitlab-Versionen möglich) ## Vorarbeiten zu Meilensteinen Bevor ein Meilenstein angelegt wird, sollten dazu mehrere Feature-Requests erstellt werden: * `[Milestone] Juli Update ` - dort wird das Fälligkeitsdatum diskutiert (geschlossen wird, sobald der Meilenstein angelegt wurde) * `[Milestone] Merge development in master` - Mergerequest von `development` in `master` * `[Milestone] Releasezweig` - Anlegen `release` Zweiges in `master` und in `development` * `[Milestone] Tagging des master Zweiges` - Taggen des aktuellen Stand des `master` Zweiges * `[Milestone] Deploy master Zweig` - Deploy des `master` Zweiges * `[Milestone] Deploy development Zweig` - Deploy des `development` Zweiges * `[Milestone] Juli Update - Schließung ` - wird geschlossen, sobald alle Issue für den Meilenstein geschlossen sind ## Namenskonvention bei Meilensteinen Auf jeden Fall sollte der Meilenstein eine klare Beschreibung bzw. Versionierung verwenden. Namen wie "Prä-München" sind nicht unbedingt hilfreich! ## make deploy auf PERMALINK wittfind.cis.uni-muenchen.de * Wenn alles ausreichend getestet wurde, dann kann auf unserem PERMALINK Rechner der Masterzweig deployed werden. Milestone haben fertig! # Aufgabe zu git: * aktivieren Sie den für Sie vom CIS bereitgestellten gitlab-Account bei gitlab.cis.lmu.de • generieren sie ssh-Keys (mit oder ohne Passphrase), und legen Sie ihren Public(!)-Key an der dafür vorgesehenen Stelle in gitlab ab (im Notfall lesen Sie Dokumentation! Einmal: ‘generate ssh keys’ und die gitlab- Dokumentation: ssh keys adden.) • nun loggen Sie sich in gitlab ein – clonen Sie dieses Repository auf ihren Rechner (von dem aus Sie ihren Public-Key erstellt und hochgeladen haben) * wechseln Sie in den development Branch. * im development Branch finden Sie die Fortsetzung der Aufgabe: `aufgabe_git.md` : https://gitlab.cis.uni-muenchen.de/wast/wast-master-2019/blob/development/aufgabe_git.md