Git

Block 8

Vielleicht hattest du eines der folgenden Probleme bereits. Sonst werden sie dir im Laufe deines Studium sicher noch begegnen.

In solchen und vielen weiteren Situationen können Version Control Systems dir dein Leben enorm vereinfachen. Eines der besten dieser System ist Git. Wie der Name schon sagt, eignen sich Version Control Systems um Ordner und Dateien zu verwalten, von denen verschiedene Versionen existieren.

Grundbegriffe

Bevor ich Git erklären kann, muss ich erst ein paar Begriffe einführen.

Repository
ist der Ort, an dem Git deine Dateien und alle Zusatzinformationen speichert. Normalerweise ist das ein verstecktes Verzeichnis mit dem Namen .git.
Branch
ist eine Kopie all deiner Dateien, die du unabhängig der anderen Kopien bearbeiten kannst. Jeder Branch hat seine eigene Geschichte.
working directory
ist dein Verzeichnis, in dem du mit den Dateien arbeitest. Ins working directory kann immer nur genau 1 Branch ausgecheckt sein. Und jede Datei kann dort auch nur einen Zustand haben.

Ein einfaches Beispiel

Ein Repository erstellen

Die drei Begriffe sollten reichen um los zulegen. Wechsle in das Verzeichnis mit den Lösungen des Python-Tutorials und schaue dir seinen Inhalt an: ls -a. Als erstes müssen wir Git fürs Verwalten der Dateien in diesem Verzeichnis vorbereiten.

git init

Git teilt dir mit, dass im Unterordner .git ein leeres Git Repository erstellt wurde. Wenn du nun wieder ls -l ausführst, siehst du, dass wirklich ein neues Unterverzeichnis existiert.

Infos zu dir

Git speichert mit jeder Version auch von wem sie erstellt wurde. Es ist deshalb wichtig, dass Git weiss wer du bist. Kontrolliere was Git denkt:

git config -l

Git gibt eine Liste seiner Konfiguration aus. Falls user.email oder user.name falsch oder nicht gesetzt ist, kannst du diese ändern:

git config --global user.name "Nicola Chiapolini" git config --global user.email "nchiapol@physik.uzh.ch"

Dank --global sollte Git von nun an für alle deine Repositories diese Angeben verwenden.

Dateien von Git verwalten lassen

Nachdem nun alles bereit ist, können wir Git mitteilen welche Dateien vom nächsten Commit betroffen sein sollen. Ein Commit ist der Befehl, mit dem Git eine neue Version speichert. Wir wollen alle .py-Dateien unter Git-Verwaltung stellen.

git add *.py

Jetzt sind die .py-Dateien vorgemerkt. Um sie wirklich zu Git hinzuzufügen, musst du noch einen Commit ausführen. Zuerst wollen wir aber anschauen, was dabei passieren würde.

git status

Ausführlich erklärt dir Git nun, welche Dateien von einem Commit betroffen wären und welche Dateien von Git ignoiert werden. Zusätzlich wird dir auch gleich mitgeteilt mit welchen Befehlen du daran etwas ändern könntest. Wir sind aber zufrieden und führen deshalb den Commit aus.

git commit -m "Dateien des Tutorials hinzugefügt"

Zu jedem Commit musst du einen kurzen Kommentar schreiben. Die Option -m erlaubt dir das direkt in der Shell zu tun. Ohne diese Option würde Git einen Editor öffnen und dich um eine Commit-Message bitten.

Du bekommst von Git eine kurze Bestätigung ausgegeben. Deren Anfang sieht wie folgt aus.

[master (root-commit) c2d161f]

Wichtig ist vor allem die dritte Zeichenkette. Das ist der Anfang der "Versionsnummer" deines Commits.

Eine neue Version erstellen

Öffne nun eine der von Git verwalteten Dateien und passe sie an. Probiere anschliessend die folgenden Befehle aus und schaue dir jeweils den Output an.

git status git diff git add das-geänderte-file.py git status git commit -m "Beschrieb deiner Änderung" git log

Alte Versionen anschauen

Um nun den Code so zu sehen wie er vor deinem letzten Commits war, verwendest du git checkout mit der Versionsnummer zu der du zurückkehren möchtest. In unserem Fall also zum Beispiel:

git checkout c2d161f

Du kannst nun den alten Code anschauen. Wenn du wieder zur neusten Version zurückkehren möchtst, tippst du:

git checkout master

master ist dabei der Name deines Branches. (Wenn du nichts verändert hast, heisst dein Hauptbranche master.)

Mit checkout kannst du alte Versionen anschauen. Wenn du deine Änderungen wirklich rückgängig machen möchtest, solltest du die Hilfe zu git revert anschauen.

Nützliche Tipps

Hilfe zu Befehlen

Git hat eine sehr umfangreiche Hilfe mit vielen Beispielen. Um dir die Hilfe zu einem Befehl anzeigen zu lassen, tippst du

git help status

Führst du git help ohne Befehl aus, so gibt Git eine nützliche Übersicht aus.

Gitk

Gitk ist ein GUI-Tool mit dem du den Zustand und die Geschichte deines Repositories anschauen kannst. Du startest es mit gitk. Im Moment wird die Anzeige noch nicht besonders spannend sein. Spätestens wenn du eine bestimmte Änderung suchst, ist gitk aber sehr praktisch.

Zu zweit zusammenarbeiten

Wirklich nützlich wird Git erst, wenn du mit anderen zusammenarbeitest. Git ist sehr flexibel und kann für die verschiedensten Abläufe verwendet werden. Hier wollen wir ein ganz einfaches Beispiel betrachten, bei dem nur zwei Personen, Alice und Bob, zusammenarbeiten wollen. Für diesen Teil solltet ihr deshalb zu zweit sein.

Alice beginnt und erstellt ein Repository im Verzeichnis /home/uzh/alice/git-test und fügt die gewünschten Dateien hinzu.

git init git add *.py git commit -m "Test-Dateien hinzugefügt"

Nun erstellt Bob einen Klon dieses Repositorys

cd ~ git clone /home/uzh/alice/git-test ls

Bobs Repository weiss bereits, wo die Version von Alice zu finden ist. Alice hingegen muss nun noch einen Verweis auf Bobs Repository erstellen:

git remote add origin /home/uzh/bob/git-test

Zusätzlich muss Alice ihre Konfiguration so anpassen, dass Git weiss welche Branches zusammengehören. (Für Bob hat git auch das beim clone-Befehl automatisch so eingestellt.)

git config branch.master.remote "origin" git config branch.master.merge "refs/heads/master"

Nach dieser Vorbereitung können Alice und Bob, jeweils in ihrem Working Directory arbeiten. Sie können Dateien verändern und neue Dateien zum Respostiory hinzufügen. Die Änderungen bleiben jeweils in ihrem Repository. Wenn sie die Änderungen ihres Partners übernehmen möchten, müssen sie erst alle ihre eigenen Änderungen commiten. Anschliessend können sie die Änderungen des Anderen holen:

git pull

Haben beide an der gleichen Datei gearbeitet, so versucht Git die Änderungen zu kombinieren. Klappt das nicht, so markiert Git die problematischen Stellen in der Datei und du musst die Konflikte von Hand beheben. Probiert das aus, provoziert (in einer Testdatei) einen Konflikt und schaut euch die resultierende Datei an.

git stash

Oben ist beschrieben, dass Alice und Bob erst die eigenen Änderungen commiten müssen, bevor sie ein pull ausführen können. Das ist meist die einfachst Lösung. Falls Alice' Änderungen aber noch nicht bereit sind für einen Commit , kann sie statt dessen auch zum Stash (einem Zwischenspeicher) hinzufügen.

git stash save git pull git stash pop

Die erste Zeile speichert alle deine Änderungen in den Stash und setzt dein working directory auf den Stand des letzten Commits zurück. Die zweite Zeile holt die Änderungen von Bob und die dritte Zeile fügt die Änderungen aus dem Stash wieder zum working directory hinzu.

Dateien an der Uni und Zuhause

Du kannst mit git auch Dateien verwalten, an denen du an der Uni und zu Hause arbeiten möchtest. Ich empfehle dir dafür ein zentrales "bare"-Repositories zu verwenden. Ein "bare"-Repository enthält selbst keine working directory sondern dient nur als clone-Quelle für andere Repositories.

Setup an der Uni

Erstelle deshalb in deinem home-Verzeichnis einen Ordner für deine zentrales Repositiories.

cd mkdir repositories

Lege dann in diesem ein "bare"-Repository an:

cd repositories git init --bare name.git

Nun wechselst du in das gewünschte Arbeitsverzeichnis (z.B.: dein home-Verzeichnis), clonest das leere Repository und füllst es mit deinen Dateien.

cd [...] git clone ~/repositories/name.git cd name [... Dateien in neuen Ordner kopieren ...] git add [...] git commit -m [...]

Als nächstes musst du die neuen Dateien ins zentrale Repository übernehmen. Das erreichst du mit push

git push origin master

Den Befehl oben mit origin master musst du nur einmal ausführen um dein zentrales Repository auf den Branch "master" aufmerksam zu machen. In Zukunft kannst du Commits einfach mit git push ins original Repository einpflegen bzw. mit git pull aus diesem übernehmen.

Setup zu Hause

Zuhause clonest du ebenfalls das zentrale Repository der Uni:

git clone ssh://user@linux.physik.uzh.ch/home/uzh/user/repositories/name.git

Danach kannst du wie gewohnt arbeiten. git pull holt die neuen Commits von der Uni und git push spielt deine lokalen Commits zurück. Bevor du pushen kannst, musst du aber alle Commits aus dem zentralen Repository übernommen haben. Meist musst du deshalb vor einem git push noch ein git pull ausführen.

Weitere Unterlagen

Das war eine kurze Einführung in Git. Wenn du mehr wissen möchtest, kannst du dir das Gittutorial (auch unter man gittutorial) anschauen. Dort findest du auch eine ausführlichere Version des Beispiels oben. Ausserdem bietet git concepts simplified eine hilfreiche Erklärung zu den verschiedenen Konzepten von Git.

Wirklich lernen mit Git zu arbeiten, kannst du aber wohl nur indem du Git benutzt. Dank der integrierten Hilfe und vielen praktischen Websites solltest du auf deine Fragen meist rasch eine Antwort finden können.

Repositiory dieses Kurses

Wir verwalten auch die Unterlagen für diesen Kurs mit git. Du kannst das Repositiory clonen mit

git clone ssh://linux/app/web/homepage/lectures/informatik/python/

Wenn du Fehler im Kurs gefunden hast, darfst du diese gerne gleich korrigieren. Du hast jedoch keine push-Rechte am Kurs-Ordner. Nachdem du dein Änderungen commited hast, musst du deshalb uns informieren. Wir werden deine Korrekturen dann ins offizielle Repository übernehmen.

Die Kursseiten sind nicht bloss in HTML. Um flexibler zu sein, werden sie mit der Skript-Sprache PHP generiert. Das bedeutet aber, dass die Seiten nicht korrekt dargestellt werden, wenn du sie direkt im Browser öffnest. Damit du deinen lokalen Kurs anschauen kannst, musst du das Kurs-Verzeichnis in den public_html Ordner verschieben. Anschliessend kannst du den Kurs wie gelernt aufrufen.