# Informatikwerkstatt __Git & GitHub__ Note: Zwei Studierende auffordern, Protokoll zu der Veranstaltung heute zu führen; Headlines und 1-2 Stichworte für die Folie mitschreiben. (Wichtig ist, dass die Protokolle nicht identisch sind) --- ## Versionskontrolle - Was ist das? * Software-Entwicklung ist heute _Teamwork_ * Software-Projekte laufen je nach Produkt über mehr als 10 Jahre * Mit der Zeit führt die zu hoher Komplexität * Nicht-lineare Entwicklung (Patches, Releases, Hotfixes)
→ Wie behält man da die Übersicht?
→ Wie verwaltet man verschiedene Entwicklungsstände?
→ Wie vermeidet man, dass Entwickler sich gegenseitig stören?
⇒ Protokollieren der zeitlichen Veränderung aller Daten
--- ## Repositories > Verzeichnisorientierte Struktur, die zur Verwaltung der Quellcodes zusätzliche zeit- und benutzerbezogeneInformationen enthält. Zusätzlich werden verschiedene Tools zur Verwaltung verwendet --- ## Was ist Git? * Dezentral organisiertes System zur [Versionsverwaltung](https://de.wikipedia.org/wiki/Versionsverwaltung) * Entstanden 2005 aus der Linux Entwickler-Community * Gut geeignet für große Projekte mit nicht-linearer Entwicklung === ### Funktionsweise * Versionshistorie: Reihe von _Snapshots_ über Dateien eines Projekts * Bei jedem Speichern legt Git eine Version des Projekts an * Sichert Zustand sämtlicher Dateien (= Snapshot) * Speichert eine Referenz auf diesen Snapshot  === ### Workflow * Drei Zustände einer Datei: geändert → vorgemerkt → committed! * Im _Arbeitsverzeichnis_ werden die Dateien bearbeitet * Im _Staging-Bereich_ werden Änderungen vorgemerkt, die in die nächste Version übernommen werden sollen * Das _Repository_ enthält ein komplettes Abbild des Projekts  --- ## Git config - Git muss mit einigen persönlichen Daten konfiguriert werden - Git fügt diese Informationen in jeden Commit ein, um immer eine vollständige Historie zu erzeugen - Mit folgenden Befehlen wird der Benutzername und EMail-Adresse gesetzt ```shell git config --global user.name "Dein Vor- und Nachname" git config --global user.email EMail-Adresse ``` - ```git config --global color.ui true``` ermöglicht eine farbige Konsolenausgabe - `git config --global core.editor "nano"` ändert den default Text-Editor zu Nano - ```git config --list``` oder ```git config {key}``` zum Überpüfen der Einstellungen --- ## Projekt erstellen * Ein Projekt entspricht einem Verzeichnis → zunächst legt man ein leeres Verzeichnis an * In dem Verzeichnis werden zwei Dateien angelegt * [.gitignore](#/8)
1
* ```readme.md``` in der eine Kurzbeschreibung des Projektes als [Markdown](https://de.wikipedia.org/wiki/Markdown) enthalten ist * Über die [Git Bash Shell](https://gitforwindows.org/)
2
wechselt man in das erstellte Verzeichnis * Dort führt man ```git init``` aus
1: die Datei muss mit einem Punkt beginnen und darf keine Endung (kein ```.xxx```) haben; Tipp: diese Datei in der Git Bash mit dem Befehl [touch](https://de.wikipedia.org/wiki/Touch_%28Unix%29) anzulegen
2: Git Bash ist auf den Pool Rechnern installiert
--- ## Genereller Workflow > In einem Repository können Dateien und Verzeichnisse erzeugt, verändert und gelöscht werden. Der generelle Workflow sollte möglichst nur kleine Veränderungen enthalten, die dann [committed](#/6/2) werden (Details in [Git Dokumentation](https://git-scm.com/book/de/v1/Git-Grundlagen-%C3%84nderungen-am-Repository-nachverfolgen))  === ### Änderungen vormerken - Git Add * Neue, veränderte oder gelöschte Dateien müssen _immer_ vorgemerkt werden * Dies tut der Befehl ```git add```; vorzumerkende Dateien müssen als Argumente übergeben werden * alle Dateien vormerken mit Punkt, z.B. ```git add .``` * [Wildcard](https://de.wikipedia.org/wiki/Wildcard_(Informatik) kann benutzt werden * Dateiname mit Endung und ggf. Verzeichnispfad * ```git status``` listet alle vorgemerkten Dateien ```shell git add . git add *.java git add src/mein_java_programm.java ``` → _Vorgemerkte Dateien sind noch nicht versioniert!_ === ### Änderung festschreiben - Git Commit * mit dem Befehl ```git commit``` werden die Änderungen festgeschrieben * dazu öffnet sich ein Editor, in den man eine _Commit-Nachricht_ eingeben muss ```shell # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch master # # Initial commit # # Changes to be committed: # new file: helloworld.java ``` * mit
Strg
+
X
gefolgt von einem
Y
speichert man den Commit * mit ```git commit -m "meine Tolle Commit-Nachricht"``` kann man alle Schritte zusammen ausführen === ### Gute Commit Nachrichten schreiben * Commit Nachrichten dienen der Kommunikation zwischen Entwicklern * Besonders wichtig, wenn mehrere Entwickler gleichzeitig an etwas arbeiten * **Ziel**: Änderungen möglichst _kurz_, aber trotzdem _präzise_ beschreiben, um anderen Entwicklern einen Überblick über gemachte Änderungen zu geben * [Tipps für eine gute Commit-Nachricht](https://wp-typ.de/entwicklung/gute-git-commits-schreiben/) === ### @Profi Um die Historie des Repositories einzusehen und die einzelnen Änderungen der Dateien einzusehen, gibt es zwei Kommandos * [git log](https://git-scm.com/docs/git-log) zeigt die gesamte [Commit-Historie](https://git-scm.com/book/de/v1/Git-Grundlagen-Die-Commit-Historie-anzeigen) mit den Informationen wie Commit-Nachricht und Benutzer an * [git diff](https://git-scm.com/docs/git-diff) zeigt die [Änderungen zwischen Commits](https://git-scm.com/book/de/v1/Git-Grundlagen-%C3%84nderungen-am-Repository-nachverfolgen#Die-%C3%84nderungen-in-der-Staging-Area-durchsehen) zeilengenau an, normalerweise zwischen dem aktuellen, noch nicht committeten Stand und dem letzten Commit (Head) --- ## Gitignore - Viele Dateien (Cache Dateien, Logs, etc.) müssen nicht versioniert werden - In der ```.gitignore``` Datei kann man Regeln festlegen, welche Dateien oder Dateimuster von Git ignoriert werden sollen ```shell # ignoriert alle Dateien mit der Endung *.log *.log # ignoriert alle test.txt Dateien in jedem Verzeichnis test.txt ```
diverse [Gitignore Vorlagen](https://github.com/github/gitignore)
=== ### @Profi Mit Hilfe einer [Whitelist](https://de.wikipedia.org/wiki/Wei%C3%9Fe_Liste) kann man in der ```.gitignore``` Datei nur die Dateitypen auflisten, die für einen Commit erlaubt sind ```shell # ignoriert alle Dateien *.* # erlaube andere Dateien mit Wildcard !*.md !.gitignore !pom.xml !*.java # ignoriere alles Erlaubte in gewissen Verzeichnissen target/ bin/ ``` --- ## Let's try [Git - The simple guide](http://rogerdudler.github.io/git-guide/) durcharbeiten mit folgender Aufgabe 1. Konfiguriere Git mit Deinem vollständigen Namen und E-Mail Adresse 2. Erstelle ein leeres Repository auf dem Desktop in einem Verzeichnis 3. Erzeuge in diesem Verzeichnis die zwei Dateien ```readme.md``` und eine ```readme.txt``` und füge in beiden die gleiche Überschrift hinzu, z.B. einen beliebigen Projektnamen 4. Passe die ```.gitignore``` so an, dass alle Dateien mit der Endung ```.txt``` ignoriert werden 5. erzeuge einen Commit mit den Daten → ... und die Tutoren überprüfen, ob es richtig gemacht wurde --- ## Git Trick & Tips * [Git Interactive Visualization](http://git-school.github.io/visualizing-git) * [Git Cheat Sheet](https://services.github.com/on-demand/downloads/de/github-git-cheat-sheet/) * [Learn Git in 30 Minutes](https://tutorialzine.com/2016/06/learn-git-in-30-minutes) * **@Profis** [Learning Git Branching](https://learngitbranching.js.org/) --- ## GitHub - Social Coding > [GitHub](http://github.com) ist die bekannteste und größte Code-Hosting Plattform und stellt Repositories für Projekte bereit, um gemeinsam Software zu entwickeln - Einfaches Projektmanagement (Issues, Project-Boards) - Genutzt von vielen Open Source Projekten, wie [MySQL](https://github.com/mysql), [Tensorflow](https://github.com/tensorflow), [Android](https://github.com/topics/android) - Organisation für Gruppenprojekte ([Google](https://github.com/google), [Microsoft](https://github.com/Microsoft), [Facebook](https://github.com/facebook)) - Webseiten mittels [GitHub Pages](https://pages.github.com/) - Meine Dissertation [LightJason](https://lightjason.org/) - Forschungprojekt [SocialCars](https://socialcars.github.io/) - Um GitHub hat sich ein ganzes System weiterer Plattformen entwickelt [Gitter](https://gitter.im/), [CircleCI](https://circleci.com/), [Zenodo](https://zenodo.org/) === ### Github Einrichtung 1. Bei GitHub [registriert](https://github.com/) _jeder_ bitte einen eigenen Account
1
* bei [Problemen](https://services.github.com/on-demand/intro-to-github/create-github-account) die Anleitung anschauen * **@Profi:** [Github Student Pack](https://github.com/): Beliebig viele private Repositories und andere Developer Tools kostenlos 2. Erstelle einen [SSH-Schlüssel](#/11) und trage ihn im GitHub-Account ein --- ### SSH ??? > Die Datenübertragung zwischen GitHub und dem PC erfolgt mittels verschlüsseltem [SSH-Protokoll](https://de.wikipedia.org/wiki/Secure_Shell) mit Hilfe eines [Schlüsselpaares](https://de.wikipedia.org/wiki/Asymmetrisches_Kryptosystem). Der Schlüssel besteht aus einem _öffentlichen_ und einem _privaten_ Teil; __nur__ der __öffentliche Schlüssel__ wird bei GitHub hinterlegt. 1. ```ssh-keygen -t rsa -b 4096 -C "EMail-Adresse"``` generiert ein neues Schlüsselpaar 2. die zwei Dateien, die den Schlüssel ergeben, findet man unter ```/c/Users/**Benutzername**/.ssh/``` * ```id_rsa``` ist der _private Schlüssel_ * ```id_rsa.pub``` ist der _öffentliche Schlüssel_ === ### SSH-Key & Github > Nun muss der Inhalt der Datei ```id_rsa.pub``` (öffentliche Schlüssel) zu GitHub übertragen werden 1. Mit ```clip < ~/.ssh/id_rsa.pub``` wird der Schlüssel in die Zwischenablage kopiert 2. Dann ruft man in der GitHub Benutzereinstellung das Menü [SSH and GPG keys](https://github.com/settings/keys) auf 3. Man erzeugt einen [neuen Schlüssel](https://github.com/settings/ssh/new) und fügt den Inhalt aus der Zwischenablage in das Feld _Key_ ein === ### SSH Verbindung testen 1. ```ssh -T git@github.com``` versucht, eine SSH-Verbindung zu Github aufzubauen 2. Beim ersten Verbindungsaufbau erscheint eine Warnung, die mit **yes** bestätigt werden muss 2. Der Befehl sollte folgende Ausgabe liefern: ```Hi **GitHub Benutzername**! You've successfully authenticated, but GitHub does not provide shell access.```
Bei [Problemen](https://help.github.com/articles/connecting-to-github-with-ssh/) findet sich eine Hilfe bei GitHub
--- ## Projekt & Repository - **Public** Repos sind einsehbar für alle Github Nutzer - **Private** Repos sind nur für Dich und für die Leute einsehbar, denen du Zugriff erteilst - _Zur Erinnerung:_ In jedem Repo sollten ein [readme.md](#/5) und eine [.gitignore](#/7) Datei vorhanden sein --- ### Github - Local & Remote  --- ## @Let's try - Mein eigenes Repository 1. Lege ein [neues Projekt / Repository](https://help.github.com/articles/creating-a-new-repository/) bei GitHub an 2. Übertrage das lokal erstellte Repository vom Desktop anhand der obigen Anleitung zu GitHub 3. Prüfe im GitHub Web Interface, ob alle Daten korrekt übertragen wurden
1: Wir geben eine Liste herum, auf die jeder von Euch bitte Euren Namen mit den zugehörigen GitHub-Accountnamen einträgt; damit erhaltet ihr Zugang zu den Projekten
Note: Tutoren sollen Studierende direkt via Laptop / PC in das Team "Studierende" eintragen --- ### Git Push > Mit ```git push``` bzw. beim ersten Mal mit ```git push origin master``` werden die Daten aus dem lokalen Repository in das GitHub [Remote Repository](https://help.github.com/articles/pushing-to-a-remote/) (siehe [Darstellung](#/10/1)) übertragen. ```master``` bedeutet, dass die Daten im Master-[Branch] gespeichert werden --- ### Git Clone > Das [Clonen](https://services.github.com/on-demand/github-cli/clone-repo-cli) kopiert das gesamte (Remote) Repository auf die lokale Festplatte. Jeder Benutzer, der sich ein Repository clont, hat somit eine vollständige Kopie der Historie. Das Verzeichnis mit allen notwendigen Daten wird automatisch erzeugt ```shell # Clonen mit automatischem Erzeugen des Verzeichnis git clone **Repository URL** # Clonen in ein definiertes Verzeichnis git clone **Repository URL** **Verzeichnisname** ``` --- ### Git Pull, Fetch & Merge > Um Änderungen (von anderen Nutzern) aus dem Remote Repository in das lokale Repository zu übertragen, wird ```git pull``` verwendet, eine [Kurzform](https://help.github.com/articles/fetching-a-remote/) von ```git fetch``` und ```git merge```. [Fetch](https://git-scm.com/docs/git-fetch) holt die Änderungen, ohne sie einzufügen; [Merge](https://git-scm.com/docs/git-merge) fügt dann die Änderungen ein, dabei können Konflikte auftreten --- ## @Let's try 1. Im letzten [Let's try](#/14) wurde das Repository zu GitHub gepusht 2. Lösche nun das lokale Verzeichnis auf dem Desktop 3. Clone das Repository ohne Angabe eines Verzeichnisses 4. Clone das Repository ein zweites Mal mit Angabe eines beliebigen Verzeichnisnamens, so dass zwei Verzeichnisse auf dem Desktop liegen 5. Mache in einem Verzeichnis eine Änderung, z.B. neue Datei einfügen oder Datei verändern 6. Pushe diese Änderung zu GitHub; prüfe, ob die Änderung gemacht wurde 7. Nun mache in dem zweiten Repository einen Pull; prüfe, ob beide Repositories wieder den gleichen Stand haben --- ## @Let's try - Für Alle 1. Clont das [Namen-Repository](https://github.com/Informatikwerkstatt/Namen) der Informatikwerkstatt 2. Ergänzt in der ```readme.md``` Eure(n) Vornamen 3. Pusht nun die Änderung ⇒ Was stellt Ihr fest? Note: Fragen, wie beide Protokolle gemergt werden sollen und Studis hinweisen keine persönlichen Daten einzutragen --- ## Merge-Konflikt > Ein [Merge-Konflikt](https://git-scm.com/book/de/v1/Git-Branching-Einfaches-Branching-und-Merging#Grundlegende-Merge-Konflikte) tritt auf, wenn zwischen Eurem letzten _Pull_ und dem durchgeführten _Push_ jemand anderes seine Änderungen gepusht hat. Ihr müsst somit zuerst einen _Pull_ machen, den [Konflikt ggf. manuell beheben](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/), dann _committen_ und _pushen_ === > Beim Autreten eines Merge Confliktes versieht Git die konfliktbehafteten Stellen mit Markern. ```Shell # Informatikwerkstatt Namensverzeichnis * Philipp * Niklas <<<<<<< HEAD * Nikita * ======= * Hendrik >>>>>>> 6b3c56095659cfc7d77887a27269ee964d9fe4bf ``` - **HEAD** ist der aktive Branch - Unter den = befindet sich der *remote* (zu mergende) Branch === Um den Merge abzuschließen: - Müssen die Konflikte behoben werden - Die Marker entfernt Werden - Die betroffenen Dateien erneut zum Stash hinzugefügt werden - Änderungen committet werden - Anschließend kann wieder gepusht werden ⇒ Bitte beseitigt alle die auftretenden Konflikte und pusht die Namensliste, so dass wir am Ende alle Namen im Repository haben --- ## Issues > In jedem Projekt treten [Fehler (Issues)](https://guides.github.com/features/issues/) auf. Mit Hilfe des Issue-Trackers können die Arbeiten zu Behebung organisiert werden. Man kann Issues vereinfacht als _Arbeitsaufgaben / Todos_ sehen. Innerhalb der Fehlerbeschreibung kann eine Diskussion statt finden. Weiterhin können Issues einzelnen Personen zugeteilt werden, die sich dann um die Lösung kümmern. __@Let's try:__ ⇒ Jede(r) erfasst bitte einen Issue mit einem einfachen Kommentar in dem [Namen-Repository](https://github.com/Informatikwerkstatt/Namen/issues)
**@Profis:** Man kann durch eine Commit-Nachricht einen Issue [automatisch schließen](https://help.github.com/articles/closing-issues-using-keywords/) und weiss damit, welche Änderungen den Fehler behoben haben
=== ## Übung/@Home: Pflichtabgabe 5 zum 27.11.2018 1. Schreibe deinen GitHub Username neben deinem Namen in das *README* im [Namen-Repository](https://informatikwerkstatt.github.io/git-github/#/19) * Jedes Teammitglied muss mindestens einen Commit haben ## @Profi - Milestones > In einem komplexen Software-Projekt müssen meist zu gewissen Zeiten bestimmte Features fertig realisiert sein. Diese Features sind meist mit Issues verbunden. Um diesen Zusammenhang darzustellen, gibt es das Konzept von [Milestones](https://help.github.com/articles/about-milestones/). Ein Milestone ist eine Liste von Issues, die bis zu einem festen Datum abgearbeitet sein müssen. Diese Organisation wird in der _agilen Software-Entwicklung_ nach [Scrum](https://de.wikipedia.org/wiki/Scrum) verwendet --- ## @Profi - Branches > Ein [Branch](https://git-scm.com/book/de/v1/Git-Branching-Branching-Workflows) ist eine abgetrennte / isolierte Umgebung, deren Änderungen keine Auswirkungen auf den Master-Code haben - Ermöglicht parallele Entwicklung an verschiedenen Features, während der Master-Code unberührt bleibt - Raum zum Experimentieren für die Entwickler - Um Branches anzulegen und zwischen ihnen zu wechseln, benutzt man das Kommando ```git checkout``` - Unterschiedliche Branches können ineinander [gemergt](https://git-scm.com/book/de/v1/Git-Branching-Einfaches-Branching-und-Merging) werden ähnlich wie bei der Konfliktbeseitigung - Wenn so genannte [Forks](https://guides.github.com/activities/forking/) eines Repositories existieren, können mit Hilfe von [Pull Requests](https://help.github.com/articles/about-pull-requests/) und dem [GitHub Flow](https://guides.github.com/introduction/flow/) die verschiedenen Stände konsistent zusammengeführt werden --- ## @Anleitung - Change Remote Repository > Android Studio bietet keine Möglichkeit ein neues Projekt in einem Ordner zu instanziieren, in dem bereits Dateien vorhanden sind. Um trotzdem ein Android Studio Projekt im bereits angelegten Projekt-Repo zu instanziieren ist einmalig ein Workaround nötig! **Git** muss für die nächsten Schritte zwingend installiert sein. 1. Öffnet euer bestehendes Projekt in Android Studio oder falls noch keins vorhanden ist erstellt euch ein neues 2. Kopiert den Inhalt der **.gitignore**-Datei vom Github-Repository in die bereits existierende **.gitignore** in euerem Projektordner (Explorer). Der vorhandene Inhalt kann überschrieben werden 3. Erstellt im Projektordner (Explorer) eine leere **readme.md**-Datei === 1. Per *ALT + F12* öffnet sich ein Terminal-Fenster in Android Studio 2. `git init` erstellt ein lokales Repository 3. `git add * ` staged alle benötigten Projektdateien 4. `git commit -m "initial commit" ` macht einen initialen commit 5. Kopiert euch die *Repository URL* (Grüner Button auf GitHub) 6. `git remote add origin` *Repository URL* Ändert das Remote Repository auf euer jeweiliges Projekt Repository 7. `git remote -v` zeigt die aktuelle Repository URL an (Überprüfung) === 8. `git push origin master` pusht den Commit in das Remote Repository > Bei Fehlern nochmal überprüfen ob die Repository URL richtig geändert wurde, oder ob die **.gitignore** mit der Datei auf GitHub übereinstimmt und eine leere **.readme** Datei erstellt wurde. 9. Überprüft auf Github ob euer Commit vorhanden ist --- ## @Links * [Git Bash](https://git-scm.com/downloads) * [Github Desktop](https://desktop.github.com/) * [Git Kraken](https://www.gitkraken.com/) * [Git Referenz](https://git-scm.com/docs) * [Pro Git](https://git-scm.com/book/de/v2) Online-Buch * [Git-Flow](https://nvie.com/posts/a-successful-git-branching-model/) für komplexere Entwicklungen