04: Versionskontrollsysteme
Code ist kompliziert, es ist normal, dass man Fehler macht und leider auch, dass man sie womöglich erst viel später bemerkt. Um alle Änderungen im Blick behalten zu können und vor allem, um gut am selben Code zusammenarbeiten zu können, gibt es Versionskontrollsysteme. Wir werden uns in dieser Session besonders mit dem bekanntesten von ihnen auseinander setzen: Git.
Inhalt
Was sind Versionskontrollsysteme und wozu sind die gut?
Ein Versionskontroll- oder -verwaltungssystem ist eine Software zur Verwaltung und Kollaboration in (Software-)Entwicklungsprojekten. Sie unterstützt Entwickler dabei, gleichzeitig am selben Code zu arbeiten.
Das Besondere an diesen Systemen ist, dass sie es erlauben, jede Änderung zu jeder Zeit rückgängig zu machen und jede beliebige Version einer Datei mit jeder beliebigen anderen Version verglichen werden kann. So kann zum Beispiel leichter nachvollzogen werden, welche Änderung einen bestimmten Fehler hervorgerufen hat, oder welcher Entwickler für welches Feature verantwortlich ist.
Für uns als Entwickler ist es auch ein guter Weg zu sehen, was sich zwischen einem Release einer Library oder eines Frameworks verändert hat, falls das Projekt keinen ausführlichen Changelog (d.h. eine Auflistung aller Änderungen) bereitstellt.
In einem Versionskontrollsystem lebt der Code in sogenannten „Branches“, in denen jede Änderung am Code anhand von sogenannten „Commits“ aufgezeichnet wird. Branches können zu einem neuen Branch zusammengeführt werden, diesen Prozess nennt man „merge“.
Am Anfang eines Projekts liegen alle Branches lokal auf dem Rechner des Entwicklers ab, aber durch die Zuhilfenahme von externen Providern wie GitHub, GitLab, Bitbucket, etc. kann der Code auf ein zentrales „Repository“ in der Cloud verschoben werden. Von diesem zentralen Repository können berechtigte Personen den Code dann „pullen“, um die neuste Version auf ihrem Rechner zu haben und ihre Änderungen an diesem Code zurück auf Repository „pushen“.
Erklärung: Was ist ein Repository?
Als „Repository“ bezeichnet man allgemein den Hauptordner eines Softwareprojektes in einem Versionskontrollsystem. So gibt es zum Beispiel ein Repository für Vue.js, und ein anderes für Node.js. Repositories können von berechtigten Benutzern auf ihre lokalen Rechner geklont werden, um in ihnen zu arbeiten.
Die bekanntesten Versionskontrollsysteme sind Git, Subversion (SVN) und Mercurial.
Was ist Git?
Git ist ein vom Linux-Begründer Linus Torvalds entworfenes und entwickeltes Versionsverwaltungssystem und besteht seit 2005.
Geschwindigkeit ist eine zentrale Säule des Projekts, die das System extrem gut darin macht, Text-Dateien zu verwalten. Es ist für binäre-Dateien wie Bilder eher ungeeignet, aber es existieren Lösungen und Erweiterungen, um diese Nachteile auszugleichen, z.B. Git LFS.
Bei Git hat jeder Rechner eine komplette und unabhängige Kopie des Repositories
im lokalen Speicher, die über push
und pull
mit einer zentralen Version
abgeglichen werden kann.
Wie funktioniert Git?
Für euren Computer sieht ein Git-Repository aus wie ein ganz normaler Ordner. Um
also ein neues Repository anzulegen, braucht ihr lediglich einen Ordner zu
erstellen und mit eurem Terminal in ihn zu wechseln. Dann könnt ihr in ihm git init
ausführen, was den versteckten Ordner .git
anlegt. In ihm verwaltet Git
euren Code, aber ihr könnt ihn getrost ignorieren.
# Unter Linux und macOS
mkdir neues-repo
cd neues-repo/
git init
In den meisten Fällen werdet ihr aber kein lokales Git-Repository von Hand erstellen, sondern ein bestehendes von einem Git-Provider wie GitHub oder GitLab klonen:
git clone benutzername@host:/pfad/zum/repo
Entwickler-Werkzeuge wie die Vue CLI, die wir noch kennenlernen werden, generieren euch außerdem neue Projekte als vorkonfigurierte Git-Repositories.
Wenn ihr eurem Repository neue Dateien hinzufügt, oder diese Ändert, müsst ihr Git davon in Kenntnis setzen. Das funktioniert folgendermaßen:
git add [dateiname oder pfad] # fügt die Datei oder dem Pfad zu den neusten Änderungen hinzu
git commit -m "Beschreibung der Änderungen" # "committed" die Änderungen in das lokale Repository
Die Nachricht, die ihr git commit
übergebt, sollte kurz und bündig beschreiben,
was ihr in diesem Commit geändert habt, zum Beispiel „Add Git-section“ oder
„Remove unneeded images“. Damit wissen eure Mitarbeiter (und euer Zukunfts-Ich)
immer genau, was ihr getan habt.
Mit git status
könnt ihr euch eine Liste ausgeben lassen, welche Dateien für
einen Commit vorgemerkt sind und welche Dateien geändert, aber noch nicht
hinzufügt wurden:
Wie ihr auf dem Bild sehen könnt, habe ich eine Datei geändert, aber noch nicht für einen Commit vorgemerkt. Außerdem habe ich bereits einen Commit lokal getätigt, aber noch nicht in das zentrale Repository verschoben.
Das kann ich nun mit git push orign master
tun. git push
bedeutet, dass ich
Commits in das zentrale Repository verschieben will, origin master
ist der
Branch in den die Änderungen verschoben werden sollen.
Erklärung: Was ist ein master-Branch?
Der master
-Branch ist der „Hauptzweig“ eures Git-Repositories.
Hier sollte die aktuellste funktionsfähige Version eures Projekts abliegen,
auch wenn in der Realität meistens ein separater production
oder
stable
-Branch exisitert und der Master-Branch die neuste Version
des Codes enthält.
Idealerweise solltet ihr für jedes neue „Feature“ eures Projekts einen neuen Branch anlegen, damit ihr diese Änderungen leicht wieder verwerfen könnt, wenn sie nicht funktionieren, oder etwas kaputt geht.
Ein neuer Branch kann mit git checkout -b name_des_branches
erstellt werden.
Wenn ihr dieses Kommando benutzt, seid ihr automatisch auf dem neuen Branch, wie
ihr mit git status
überprüfen könnt.
Wollt ihr zurück zum master oder einem anderen Branch wechseln, könnt ihr das
mit git checkout name_des_branches
tun, also z.B. git checkout master
. Einen
Branch löschen könnt ihr mit git branch -d name_des_branches
. Mit git push origin name_des_branches
könnt ihr außerdem einen Branch in das zentrale
Repository verschieben.
Wart ihr brave Entwickler und habt euer neues Feature in einem Feature-Branch aufgebaut und fertiggestellt, könnt ihr es so mit eurem Master-Branch zusammenführen:
git checkout master # vom feature-Branch in den master-Branch wechseln
git merge feature_branch # den Branch mit dem Namen feature_branch mit master zusammenführen
Git versucht dann die Änderungen automatisch anzuwenden. Klappt das nicht, wird
Git euch mitteilen, dass es Konflikte gibt, die ihr dann manuell beheben müsst.
Habt ihr alle Konflikte behoben, müsst ihr die geänderten Dateien wieder mit
git add
hinzufügen und den Merge committen.
Wollt ihr nur wissen, welche Unterschiede es zwischen zwei Branches gibt, könnt
ihr euch das mit git diff quell_branch ziel_branch
ausgeben lassen.
Arbeitet ihr zum Beispiel zu zweit an einem Feature, solltet ihr bevor ihr
Änderungen macht immer git pull
ausführen, um die aktuellste Version aus dem
zentralen Repository in euer lokales Repository zu laden und mit eurem aktuellen
Stand zu mergen. Seid ihr mit euren Änderungen fertig, pusht ihr diese zurück
in das zentrale Repository.
Geht das nicht leichter?
Das Terminal ist super, wenn ihr einmal feststeckt und nach Fehlermeldungen googlen wollt, aber für die grundlegenden Aktivitäten wie add, commit, push, branch und pull, sowie das Beheben von merge-Konflikten, könnt ihr das GUI in Atom verwenden, das alles visueller und etwas leichter verständlich macht.
Mehr Infos
Hier findet ihr eine nette Übersicht aller wichtigen Kommandos, sowie andere nützliche Tipps. Hier findet ihr außerdem ein ausführliches Buch über Git und seine Funktionen, das ihr online lesen könnt (Achtung es sind noch nicht alle Teile auf Deutsch übersetzt).
Wie so oft empfehle ich euch aber auch hier einfach mit den Grundlagen anzufangen und nur bei konkreten Fragen Google oder diese Ressourcen zu verwenden, damit ihr euch nicht mit Dingen verwirrt, die nur in seltenen Fällen nötig sind.
Was sind Git-Provider?
Wie bereits angemerkt ist es zur Kollaboration (und auch für die eigene Seelenruhe) wichtig, den geschriebenen Code nicht nur in einem lokalen Git- Repository abzulegen, sondern auch in ein zentrales Repository in der Cloud zu verschieben. Nicht nur erlaubt diese Praxis es euch und euren Mitarbeitern leicht am selben Code zu arbeiten und immer die aktuellste Version zu verwenden, euer Code bleibt zudem auch erhalten, falls eurem Rechner einmal etwas passieren sollte (oder ihr von mehreren unterschiedlichen Rechnern aus an eurem Code arbeiten wollt 😉).
Natürlich könntet ihr euer lokales Repository in den synchronisierten Ordner eines Cloud-Storage-Anbieters eurer Wahl (z.B. Google Drive, oder Dropbox) ablegen und so synchronisieren, allerdings gehen euch dann einige Vorteile von Git verloren und allerhand Fehler können auftreten. Stattdessen bietet es sich also an, einen eigens dafür geschaffenen Dienstleister zu verwenden, einen sogenannten Git-Provider.
Der wohl bekannteste Git-Provider ist GitHub, der im vergangenen Jahr von Microsoft aufgekauft wurde, aber es existieren auch Alternativen wie Bitbucket, oder das von uns verwendete GitLab.
Im Kern funktionieren alle Git-Provider mehr oder weniger gleich: sie geben euch die Möglichkeit, mehrere zentrale Git-Repositories für eure verschiedenen Projekte anzulegen und diese dann auf eure Computer zu klonen, wo ihr sie wie lokale Git-Repositories verwenden könnt. Zusätzlich bieten sie auch Features wie Wikis für Dokumentationen, ein Ticket-System für Bugs und Aufgabenverwaltungen an. GitLab (und inzwischen glaube ich auch GitHub) bietet zusätzlich noch einen sogenannten CI-Dienst an, mit dem wir uns in einer späteren Session beschäftigen werden.
Warum GitLab?
Mein erster Git-Provider was Bitbucket, denn es war zu der Zeit der einzige Anbieter, der es erlaubte kostenfrei private Repositories anzulegen (GitHub bietet erst seit diesem Jahr kostenlose privater Repositories an).
Erklärung: Was ist ein privates Repository?
Bei allen Git-Providern wird zwischen privaten und öffentlichen Repositories unterschieden. Private Repositories sind nur für diejenigen sichtbar, denen Zugriffsrechte auf dieses Repository gewährt wurden. Nur sie können es klonen, die Dateien einsehen, und so weiter. Öffentliche Repositories können von jedem im Internet eingesehen und geklont werden (so funktioniert Open Source), aber natürlich kann niemand einfach irgendwas an eurem Code ändern, wenn ihr nicht die Erlaubnis dazu erteilt. Möchte jemand eine Änderung zu eurem Code beitragen, muss er/sie das Repository klonen, einen Branch für seine/ihre Änderungen anlegen und schließlich eine Anfrage an euch senden, diesen Branch mit eurem Code zu mergen. Bei GitHub nennt man das eine „pull request“, bei GitLab eine „merge request“.
Ich war mit Bitbucket aber nie wirklich zufrieden und als GitLab langsam bekannter und stabiler wurde, wechselte ich dorthin und bin seither sehr glücklich damit.
GitLab hat meineserachtens einige Vorteile:
- Unbegrenzt viele kostenlose Repositories und Gruppen (öffentlich und privat)
- Übersichtliches UI (in Vue.js geschrieben 🎉)
- Guter Issue-Tracker
- Kostenfrei nutzbare CI/CD
- Pages-Support
- Uvm.
Außerdem ist GitLab open-source. Das bedeutet, dass man leicht neue Features erbitten und Fehler melden kann. Falls GitLab.com einmal nicht mehr betrieben werden können sollte, könnte man sich auch einfach selbst eine GitLab-Instanz auf einem Server installieren und müsste sich nicht an ein neues Tool gewöhnen, man ist also vollkommen unabhängig. Das ist weder bei GitHub, noch Bitbucket gegeben.
Praxis
Git Installieren
Je nach Betriebssystem unterscheiden sich die Installationsanweisungen für Git.
Auf Ubuntu könnt ihr einfach sudo apt install git
ausführen, um die aktuellste
verfügbare Version von Git zu installieren.
Auf macOS könnt ihr git --version
verwenden, um zu überprüfen, ob Git nicht
schon installiert ist. Falls es nicht installiert sein sollte, werdet ihr
gefragt werden, ob ihr die Xcode Command Line Tools installieren wollt, die Git
enthalten, alternativ könnt ihr auch versuchen, Git über das Installer-Paket
hier zu installieren.
Windows-Nutzer installieren Git über die Setup-Datei, die hier heruntergeladen werden kann.
Nachdem Git installiert wurde, könnt ihr mit git --version
die aktuell
installierte Version ausgeben lassen:
Bekommt ihr eine aktuelle Version (2 oder höher) angezeigt, könnt ihr nun Git eure Identität mitteilen (dieser Schritt ist wichtig, damit eure Commits euch zugewiesen werden können):
git config --global user.name "Max Muster" # Euer Name
git config --global user.email "mmuster@example.com" # Eure Email-Adresse
Um zu überprüfen, ob alles geklappt hat, könnt ihr euch mit git config --list
eine Liste aller gesetzten Informationen ausgeben lassen.
GitLab Account anlegen
Ein GitLab.com-Account kann kostenlos auf der GitLab-Website
angelegt werden. Klickt dazu einfach oben rechts auf „Register“ und meldet euch
an. Verwendet zur Anmeldung die Email-Adresse, die ihr auch im vorherigen
Schritt bei user.email
angegeben habt. Ich empfehle euch außerdem ein
einzigartiges und sicheres Passwort zu wählen, das ihr euch gut merken könnt
– falls jemand Zugriff auf euren GitLab-Account bekommen sollte, kann dieser
Angreifer potenziell sehr viel Schaden anrichten.
Habt ihr euch angemeldet, solltet ihr in eurem Dashboard landen, das mehr oder weniger folgendermaßen aussehen wird (natürlich ohne Projekte, da ihr noch keine angelegt habt):
Von diesem Dashboard aus habt ihr einen Überblick über all eure Projekte (Repositories) auf GitLab und könnt auch einfach neue über den Button oben rechts anlegen.
Der Gruppe „HM-Webdesign“ beitreten
Schickt mir bitte eine Email mit eurem GitLab-Nutzernamen und der Email-Adresse, mit der ihr euch angemeldet habt, damit ich euch zur HM-Webdesign-Gruppe hinzufügen kann. Ihr solltet per Mail benachrichtigt werden, sobald ihr Zugriff habt.
In dieser Gruppe legt ihr bitte später die Repositories (auf GitLab „Projects“ genannt) für eure Apps an, wenn es soweit ist. So können wir alle den Code der Anderen sehen und davon lernen und ich habe für die Bewertung alles an einem Ort.
Ein Übungs-Repository anlegen
Mit eurem frisch-gebackenen GitLab Account könnt ihr euch nun gleich ein erstes
Repository für eure ersten Übungsprogramme anlegen. Klickt dafür im Dashboard
auf „New Project“, gebt diesem einen eindeutigen Namen, und stellt sicher,
dass ihr das Projekt in eurem eigenen Benutzernamen anlegt, nicht unter
hm-webdesign
.
Nach dem Erstellen werdet ihr auf die Hauptseite eures neuen Repositories weitergeleitet und wenn ihr auf dieser Seite etwas herunter scrollt, seht ihr einige nützliche Kommandos, die es euch erlauben, das Repository entweder frisch auf euren Rechner zu klonen, einen bestehenden Ordner in ein Git-Repository zu verwandeln und auf GitLab zu pushen, oder ein bestehendes lokales Git-Repository mit eurem GitLab-Repository zu verbinden:
Wie immer beim Programmieren gilt: ihr müsst euch nicht alles merken, nur wissen, wo es steht. 😉
Weitere Gestaltung
Im Praxisteil der letzten Session habt ihr das Konzept für eure App entwickelt und eine Design-Sprache festgelegt, sowie erste Komponenten ausgestaltet. Jetzt habt ihr Zeit, diese Komponenten zu verbessern und die Screens eurer App zu gestalten. Überlegt euch, wie alles zusammen hängt und stellt euch vor wie eure Nutzer eure App verwenden. Ihr solltet für alle wichtigen Fragen eures Nutzers (z.B. „Wie erstelle ich ein neues ToDo?“, „Wie lösche ich ein ToDo?“, „Wo finde ich abgeschlossene ToDos?“, etc.) einen Screen haben, der die Antwort auf die Frage beschreibt bzw. darstellt. Das ist ein langer und zeitaufwändiger Prozess, es muss also nicht alles auf einmal fertig werden. Wie immer könnt ihr mir eure Ergebnisse zeigen und um Feedback bitten. Das geht am einfachsten, indem ihr mich zu euren Figma-Dateien hinzufügt, oder mir eine Mail mit einem Anhang schickt, falls ihr nicht mit Figma arbeitet.
Außerdem ist es langsam an der Zeit, euch ein Logo für eure App zu überlegen, und wie das Home-Screen und Favicon eurer App aussehen sollte.
Ein paar Tipps hierzu:
- Das Favicon ist sehr klein, packt also nicht zu viele Details in es hinein
- Das Favicon kann auf hellen und dunklen Hintergründen erscheinen, also habt entweder keine Transparenz, oder stellt sicher, dass es auf beiden Hintergründen funktioniert
- Das Home-Screen-Icon wird bei modernen Android-Versionen automatisch beschnitten, stellt also sicher, dass euer Icon vollständig innerhalb einer kreisförmigen „safe-zone“ mit mindestens 10% der Bildbreite Abstand auf allen Seiten im zentrum eures Home-Screen-Icons liegt, mehr dazu hier und hier
In der nächsten Session geht es endlich mit dem Programmieren los! Ich werde euch eine Einführung in die Programmierung geben und ihr werdet eure ersten Programme schreiben. 😁