====== Git & GitHub ====== Du kennst das Problem: Du arbeitest an einem Dokument (Word, Python, ...) und du möchtest eine **Sicherheitskopie** erstellen. Die Idee ist, dass du zu dieser Version zurückkehren kannst, solltest du bei weiteren Änderungen etwas vermurksen. Dieses Vorgehen funktioniert (und zugegeben, ich mache das manchmal auch so), ist aber nicht sehr elegant, da es eine grosse Fülle an Dokumenten erzeugt, kurz: Es müllt deinen Computer zu (benötigt viel Speicherplatz, Ordner wird unübersichtlich). Betrachten wir ein **Beispiel**: Du schreibst eine Abschlussarbeit und es fehlt nur noch das Fazit. Machst du nun vor dem Schreiben des Fazits eine Kopie der Arbeit, hast du am Schluss zwei Dokumente, die zu 95% oder so identisch sind und unterscheiden sich nur darin, dass das eine das Fazit enthält und das andere nicht. Dies ist nicht sehr (platz)effizient. Eleganter ist die Verwendung von einem **Versionierungstool**. Dieses erlaubt es einem **Snapshots** von einem Dokument zu erstellen, also den aktuellen Zustand eines Dokuments zu speichern. Solche Tools machen nicht immer eine ganze Kopie vom Dokument, sondern //merken sich nur die Unterschiede// seit dem letzten Snapshot. Über das Tool kann man dann auch ältere Snapshots zurückgreifen. Die Informationen zu den verschiedenen Snapshots wird typischerweise in einem versteckten Ordner abgelegt. Im Beispiel von oben wird also nicht die ganze Abschlussarbeit kopiert, sonder das Tool merkt sich nur, dass das Fazit neu hinzugekommen ist. Die **versteckten Ordner / Dateien** kannst du wie folgt ein- und ausblenden. Gehe dazu in den File-Explorer / Finder: * Windows: Ansicht / Ausgeblendete Elemente * Mac: CMD + Shift + . Wir arbeiten hier mit dem Versionierungstool **Git**, welches gleichzeitig auch der Industriestandard und gratis ist. Weiter arbeiten wir mit **GitHub**, eine Art Online-Cloud für Projekte, die mit Git versioniert werden. GitHub ist eine hervorragende Lösung für **Kollaborationen**: Wann immer ihr zusammen am gleichen Code arbeitet, sollt ihr dies über GitHub tun. ===== - Git ===== **Git** ist ein relativ einfaches und sehr mächtiges Versionierungstool, welches von sehr vielen Programmieren verwendet wird. Git wurde von Linux-Erfinder Linus Torvalds entwickelt und der Name //Git// bedeutet umgangssprachlich auf englisch 'Blödmann'. Zur Wahl des Namens sagt Torvalds spasseshalber: "I'm an egotistical bastard, and I name all my projects after myself. First //Linux//, now //Git//." Und ein bisschen ernsthafter: "The joke 'I name all my projects for myself, first Linux, then git' was just too good to pass up. But it [git] is also short, easy-to-say, and type on a standard keyboard. And reasonably unique and not any standard command, which is unusual." ==== - Für was ist git (nicht) geeignet? ==== Git ist perfekt geeignet für die Verwaltung von Projekten, die einfache Textdateien beinhaltet, wie zum Beispiel `.txt`, `.md`, `.tex` oder Programmiercode (z.B. `.py`). Ungeeignet hingegen ist git ist für Bilder, Videos, Musik, zip-Files, Office-Dateien (`.docx`,...) oder PDF. Möchtest du mit einer Kollegin zusammen an einem Photoshop-Projekt arbeiten, so suchst du dir besser eine andere Lösung (z.B. OneDrive). ==== - Installation ==== Das folgende **Tutorial** begleitet dich durch die Installation und die wichtigsten Schritte: Das Wichtigste wird hier doch noch kurz erläutert. Auf MacOS und Linux ist git bereits installiert. Falls du auf Windows arbeitest, lade git hier herunter und installiere es . Bei der Installation wirst du einige Entscheidungen treffen müssen. Wähle die folgenden Option: * "Use Git from Git Bash only" * "Use the OpenSSL library" * "Checkout Windows-style, commit Unix-style line endings" * "Use MinTTY" * Wähle bei den "Configuring extra options" alle Optionen an ==== - Command line tool vs. Client ==== Git ist ein Command line / Terminal Tool. Es gibt aber auch Git-Clients - Programme mit einer graphischen Oberflächen. Auch wenn die Command Line am Anfang etwas abschreckend wirkt, so lohnt es sich, sich an diese zu gewöhnen. Verwende auch deshalb //keine// Clients, weil die Verwendung von solchen deinen Coolnessfactor um 39.2% reduziert! Hier ein paar wichtige **Command Line Befehle:** * `dir` (Windows), `ll` und `ls` (Unix): Zeigt alle Dateien und Unterordner im jetzigen Ordner an * `mkdir meinOrdner` erstellt einen neuen Ordner mit Namen *meinOrdner* * `cd meinOrdner`: navigiere in den Ordner *meinOrdner* hinein. `cd` steht für *change directory*, also *wechsle Ordner* * `cd ..`: navigiere zum übergeordneten Ordner * Tippe die ersten Buchstaben eines Befehls, nutze dann die TAB-Taste zur Autovervollständigung. Mehrmaliges drücken geht durch alle Möglichkeiten hindurch. ==== - Wichtigste Befehl: git status ==== Der wichtigste git-Befehl ist git status Er zeigt dir den **aktuellen Status** eines Repositories an. **Tipps:** * Tippe immer *git status*, wenn du dir //unsicher// bist, was du machen sollst. * Gerade am Anfang bietet es sich an, //nach jedem Schritt// den Status zu überprüfen. ==== - Mit Git arbeiten ==== Ein Ordner, der mit git verwaltet wird, nennt man ein **Git-Repository**. Um die Verwaltung mit git zu beginnen, öffne die *Git Bash* unter Windows oder den ganz normalen Terminal unter Mac/Linux und navigiere in den Ordner, der als Git Repository dienen soll. Dieser kann bereits Dateien und Unterordner beinhalten. Um ein **neues Git Repository zu initialisieren**, tippe git init Dein lokales Repository besteht aus drei **Instanzen**, die von git verwaltet werden. Die erste ist das **working dir**, welches die *echten Dateien* enthält. Die zweite ist der **Index**, welcher als *Zwischenstufe* agiert und zu guter Letzt noch der **HEAD**, der auf deinen *letzten Commit* zeigt. {{:talit:git_wokingdir_index_head.png?552|}} Hast du gerade ein Repository initialisiert, werden nach `git status` bereits vorhandene Dateien in rot angezeigt: Diese Files befinden sich erst im *working dir* und sind deshalb *untracked*, sie werden also von Git ignoriert. Damit ein oder mehrere Files mit git verwaltet werden können, müssen sie dem **Index hinzugefügt** werden: **Einzelnes File** dem **Index hinzuzufügen**: git add **Alle Files** (auch in Unterordnern) dem **Index hinzuzufügen**: git add . Tippst du wieder `git status` werden diese Dateien jetzt in Grün dargestellt. Nun musst du deine **Änderungen noch bestätigen**, also **committen**: git commit -am "initial commit" Mit diesem ersten Commit hast du eine erste Version erstellt, quasi einen ersten *Snapshot*. Der letzte Teil des Befehls ist eine **Commit-Nachricht**, für welche folgende Regeln gelten: * Commit-Nachrichten sollten auf **Englisch** geschrieben werden. * Sie sollen zwar **kurz** aber auch ... * möglichst **aussagekräftig** sein. Ein Beispiel für eine ordentliche Commit-Nachricht: *some bugs in myapp.py fixed, runs well now* Gerade wenn mehrere Personen am gleichen Projekt arbeiten, sind diese Nachrichten sehr wertvoll! Tippst du nun `git status`, so erscheint die Nachricht *nothing to commit, working tree clean*. Nun kannst du weiter an deinen Dokumenten arbeiten. Immer, wenn du einen **neuen Commit/Snapshot** erstellen möchtest, gehst du wie oben beschrieben und hier kurz zusammengefasst vor: # Übersicht verschaffen über Status des Repositorys git status # Neue Files hinzufügen git add ... # Change committen: git commit -am "describe your commit here. no nonsense please!" # vergewissere dich, dass alles i.O. git status Dies sind die Befehle, die du 95% der Zeit benötigst. Lerne sie auswendig! ==== - Gitignore ==== Führt man einen Programmcode aus, werden oft im Hintergrund Dateien generiert, die für uns nicht von Relevanz sind. Das Gleiche geschieht, wenn man mit LaTeX (die nerdig-coole Alternative zu Word) Textdokumente erstellt. Diese Build-Artefakte werden bei jedem erneuten Ausführen erstellt und sollten auf keinen Fall dem Git-Repository hinzugefügt werden oder genauer: Sie sollen explizit ausgeschlossen werden. Dazu kann man in einem eine Datei `.gitignore` hinzufügen, in welcher man festlegt, welche Dateien oder Dateiformate ausgeschlossen, also von Git ignoriert, werden sollen. Das standardmässige .gitignore-File von GitHub für Python-Projekte ist: {{ :talit:gitignore_python.zip |Gitignore-File für Python}} ==== - Weitere Befehle ==== Die oben benutzen Befehle reichen für die meisten Alltagsanwendungen aus. Hier noch ein paar weitere Befehle, die manchmal wertvoll sein können: **Datei/Ordner von Git entfernen** ohne es von lokalem Dateisystem zu löschen git rm --cached fileName git rm -r --cached folderName **Zeige alle von Git getrackten Dateien** git ls-files # oder: git ls-tree -r master ===== - GitHub ===== **GitHub** ist eine Art //Cloud-Service für Git-Repositories//. Im Gegensatz zu normalen Cloud-Anbietern wie OneDrive oder Dropbox werden Änderungen an Dokumenten nicht immer in real time hochgeladen. Stattdessen muss man Änderungen explizit auf GitHub //pushen//. Beachte, dass ein GitHub-Repository kann entweder **private** (nur für Author zugänglich und Leute, die explizit dazu berechtigt werden) oder **public** (für alle zugänglich) sein. Typische **Verwendungszwecke** von GitHub: * Backup (privat) * Kollaborationen in Projekten (privat) * Open Source Code veröffentlichen (public) * Ausbildung: Abgabe von Aufträgen (privat) {{:talit:github_idea.png|}} ==== - Account ==== Erstelle einen Account auf GitHub: . Beantrage einen Studenten-Account, damit verschaffst du dir Vorteile. ==== - Neues GitHub-Repository anlegen ==== Gehe auf die http://github.com/ und logge dich ein. Klicke unter *Repositories* auf *New*. Gib dem Repository einen Namen. Dieser soll die folgenden Kriterien erfüllen. * auf Englisch * kurz aber zum Projekt passend * keine Leerzeichen (verwende Underlines _) Gib an, ob das Repo *private* oder *public* sein soll. In den meisten Fällen solltest du *private* wählen. Füge ein passendes Gitignore-File hinzu. Wàhle die Programmiersprache deines Projekts. Für grössere Projekte oder für solche, die du veröffentlichen möchtest, lohnt es sich, die Option *Initialize this repository with a README* anzuwählen. Im zweiten Fall sollte man sich auch mit Lizenzen auseinandersetzen und eine solche hinzufügen. Dann kannst du das Repo erstellen. **Klone** das Repo nun auf deinen Computer. Hast du auf GitHub das Repo geöffnet, so kannst du unter *Clone or download* den Link zum Repo kopieren git clone https://github.com/username/repo_name.git ==== - Mit GitHub arbeiten ==== Hast du lokal auf deinem Computer Änderungen vorgenommen und diese committed (siehe [[talit:git#mit_git_arbeiten|Mit git arbeiten]]), so kannst du diese auf GitHub **pushen**: git push Gehe nun auf GitHub und vergewissere dich, dass alles geklappt hat. Hat in der Zwischenzeit deine Kollegin ins gleiche Repository gepushed, kannst du selbst deine Änderungen nicht pushen. Stattdessen musst du die aktuelle Version von GitHub herunter**pullen**: git pull Git versucht nun, deine Änderungen mit denjenigen deiner Kollegin zu verbinden - zu **mergen**. Habt ihr unterschiedliche Files oder das gleiche File an unterschiedlichen Stellen bearbeitet, so sollte dies zu keinen Problemen führen. Habt ihr aber identische Stellen im gleichen File bearbeitet, so führt dies zu einem **merge conflict** - und dieser muss behoben werden. Öffne dazu das File und suche den Konflikt, dieser wird deutlich angezeigt, und löse diesen. Danach kannst du die Änderung committen und deine Änderungen nach GitHub pushen. Zusammengefasst die wichtigsten Arbeitsschritte: # Übersicht verschaffen über Status des Repositorys git status # Neue Files hinzufügen git add ... # Change committen: git commit -am "describe your commit here. no nonsense please!" # Auf GitHub pushen git push Falls beim Pushen die Meldung kommt, dass bereits jemand vor dir gepushed hat: # aktuellste Version herunter pullen git pull # löse merge conflicts, falls es welche gibt # Change committen: git commit -am "describe your commit here, explain how you solved merge conflict" # Auf GitHub pushen git push ==== - Kollaborationen ==== Du kannst ein privates Repo für andere GitHub-Benutzer freigeben, damit diese mit dir an diesem Arbeiten können. Wähle dazu auf GitHub das Repo an, klicke auf *Settings / Collaborators* und wähle den Benutzer aus. Mit einem gratis Account von GitHub kannst du bis zu drei Collaborators zu einem Repo hinzufügen. ==== - Diff ==== Mit dem folgenden Befehl werden die sämtliche Änderungen seit dem letzten Commit angezeigt: git diff HEAD Das Keyword HEAD ist ein Zeiger auf den letzten Commit. Oft ist es auch nützlich, die Unterschiede zwischen zwei Commits zu sehen. Jeder Commit ist durch eine eindeutige lange Nummer (Zahlen und Buchstaben) gekennzeichnet, z.B. 48k845173f... Die Nummern der Commits findest du mit dem Befehl: git log Falls es sich um ein GitHub-Repository handelt, kannst du die Commit-Nummern auch dort nachschlagen. Kopiere dir die Nummern der zu vergleichenden Commits heraus. Tatsächlich reicht es, wenn man die ersten paar Ziffern der Nummer nimmt. Die Unterschiede anzeigen kannst du nun wie folgt: git diff commitnumber1 commitnumber2 Interessiert dich nur, welche Files überhaupt verändert wurden, so füge die Option `--name-only` hinten an den Befehl: git diff commitnumber1 commitnumber2 --name-only Weitere Infos zu diesem Thema findest du hier: https://git-scm.com/docs/git-diff ==== - Weitere GitHub Dinge ==== Mit den oben beschriebenen Schritten sollten die meisten deiner GitHub Wünsche abgedeckt sein. Falls nicht, findest du in diesem Kapitel weitere Tipps. === - Repository lokal erstellen === Oben haben wir gesehen, wie man auf GitHub ein neues Repository erstellen und es dann auf den eigenen Computer klonen kann. Alternativ (aber etwas umständlicher) kannst du ein bereits auf deinem deinem Rechner vorhandenes Projekt, welches du mit Git verwaltest, auf GitHub pushen. Erstelle zuerst auf GitHub ein neues Repository. Üblicherweise hat dieses den gleichen Namen wie der Ordner deines Projekte (ist aber kein Muss). Wähle kein Gitignore-File und wähle die Option *Initialize this repository with a README* nicht an. Nun musst du das lokale Repo mit dem leeren auf Repo auf GitHub verbinden: git remote add origin https://github.com/username Das Repo auf GitHub wird das **remote Repository** genannt (remote = entfernt). Das (oder die) remote Repository eines Projekts kann man anzeigen mit git remote -v Nun können die Daten auf GitHub gepushed werden: git push origin master Möchte man ein **remote Repository entfernen**, so tippt man git remote rm origin === - Branches === TODO === - Alternativen zu GitHub === Es gibt andere Dienste, die in etwa das Gleiche anbieten wie GitHub, wie z.B. *Bitbucket*. === - Git-Clients === Git-Clients sind Programme mit graphischen Oberflächen, mit denen man die oben beschriebenen Arbeitsschritte ebenfalls vornehmen kann. Ein Beispiel dafür ist **GitKraken**. Es ist aber empfohlen, sich daran zu gewöhnen, mit der Git Bash zu arbeiten. Einige IDEs wie *Visual Studio* oder *Visual Studio Code* haben einen integrierten Git-Client.