2.2 Git Basics
Git kann auf unterschiedliche Arten eingesetzt werden. Es gibt graphische Oberflächen und die meisten Git-Server Software bieten Weboberflächen, welche das interagieren mit Git Repositories kinderleicht gestalten. Da diese Oberflächen meist sehr Produktspezifisch sind und oft auch nicht alle Funktionen beinhalten, werden hier nur die Kommandozeilen Befehle angeschaut.
Inhalt
- Konfiguration von Git
- Hilfe
- Ein Git Repository anlegen
- Änderungen verfolgen und im Repository speichern
- Anzeigen der Commit Historie
- Änderungen rückgängig machen
- Mit Remotes arbeiten
Konfiguration von Git
Git kann an verschiedenen Orten konfiguriert werden:
/etc/gitconfig
enthält die Werte, welche für alle Benutzer auf dem System gelten. Die Datei kann mitgit config --system
gelesen oder editiert werden. Man braucht Administrator- oder Superuser-Rechte um die Datei zu editieren.~/.gitconfig
oder~/.config/git/config
enthält die Werte, welche für den aktuellen Benutzer konfiguriert sind. Mitgit config --global
können Werte gesetzt oder ausgelesen werden.- Die Datei
config
im.git
Verzeichnis innerhalb eines Repositories enthält die Konfiguration, welche nur für dieses Repository zählt. Das Flag fürgit config
ist in diesem Fall--local
, ist jedoch in der Regel die Standardoption und kann weggelassen werden.
Jede dieser Konfigurationen wird von der nächsten überschrieben, sodass die Repository bezogene Konfiguration den höchsten Wert hat. Um zu die aktuelle Konfiguration und ihren Ursprung anzusehen kann folgender Befehl ausgeführt werden:
|
|
Konfigurationsbeispiele
Das wichtigste ist der Name und die Email Adresse, diese Angaben werden an jeden Commit angehängt:
|
|
Wie wir bereits gelernt haben, schreiben wir mit dem --global
Flag in die Konfiguration in unserem home
Verzeichnis und sie gilt somit für alle Repositories, welche wir mit unserem User bearbeiten. Wollen wir dies fur ein bestimmtes Repo übersteuern, haben wir immer noch die Möglichkeit dies mit --local
zu machen.
Eine weitere Konfiguration die evtl. hilfreich sein kann ist core.editor
mit welcher der Texteditor definiert werden kann. Git benutzt, falls hier nichts definiert ist, den Standard-Editor des Systems.
Hilfe
Git bietet mehrere Möglichkeit, wie man an Hilfe gelangt, wenn man einmal nicht weiter weiss:
|
|
Wenn man also nicht mehr genau weiss, wie dies mit der Konfiguration von Git funktioniert kann man sich folgendermassen weiterhelfen:
|
|
Ein Git Repository anlegen
Um lokal ein neues Git Repository anzulegen gibt es zwei Varianten:
- Umwandeln eines Verzeichnis, welches (noch) nicht mit Git verwaltet wird, zu einem Git Repository
- Klonen eines existierenden Repositories von einem anderen Ort
Ein Verzeichnis zu einem Git Repository verwandeln
Um aus einem Ordner ein Git Repository zu erstellen, muss man zuerst in den Ordner wechseln und anschliessend das Repository initialisieren:
|
|
Der zweite Befehl erzeugt ein .git
Unterverzeichnis, welches die Repository Daten beinhaltet. Im Moment werden noch keine Dateien von Git verwaltet, diese müssen zuerst hinzugefügt (git add
) und dann committed werden (git commit
). Wenn wir von einem leeren Ordner aus gehen, müssen die Dateien natürlich zuerst noch erstellt werden:
|
|
Ein bestehendes Repository klonen
Um ein Repository zu klonen wird der Befehl git clone
verwendet:
|
|
Git legt dann automatisch ein Verzeichnis libgit2
an mit allen Dateien und initialisiert das Repository mit einem .git
Verzeichnis im Hauptverzeichnis. Wird hinter der URL noch etwas angegeben, wird dies als Name des Zielverzeichnisses interpretiert:
|
|
Änderungen verfolgen und im Repository speichern
Zur Erinnerung, eine Datei in einem Git Folder kann vier Zustände haben:
- Untracked: Die Datei liegt im Ordner, wird aber nicht von Git versioniert
- Unmodified: Die Datei wird von Git versioniert, sie ist seit dem letzten Commit unverändert.
- Modified: Die Datei wurde seit dem letzten Commit verändert
- Staged: eine neue oder editierte Datei wurde für den nächsten Commit vorgemerkt.
Der Befehl zum überprüfen, ob man Dateien in einem anderen Zustand als unmodified
hat ist git status
:
|
|
Wollen wir nun die Änderungen der Datei 2_git/2_basic/README.md
(oder die Datei .gitignore
) zum nächsten Commit hinzufügen, also stagen, können wir dies mit git add <pfad/zur/datei>
. Im Beispiel oben sehen wir, dass die Datei 2_git/README.md
bereits gestaged ist. Ändern wir diese Datei erneut, wird die Datei sowohl bei Changes to be committed: wie auch bei Changes not staged for commit: auftauchen. Einmal mit den Änderungen, welche wir bereits gestaged haben und einmal mit den Änderungen, welche wir nach dem Stagen (git add
) gemacht haben. Wollen wir beide Änderungen im gleichen Commit, können wir die Datei einfach wieder mit git add
stagen und anschliessend commiten. Wollen wir stattdessen die Änderungen in separaten Commits, commiten wir zuerst die schon gestagten Änderungen und stagen und committen anschliessend die zweiten Änderungen.
.gitignore
Bevor wir lernen, wie man seine Änderungen commited, wollen wir noch kurz die spezielle Datei .gitignore
anschauen. In dieser Datei können Dateien erfasst werden, welche Git nicht als untracked aufzählen soll, respektive ignorieren soll. Die Datei wird ganz normal wie jede andere auch ins Repo eingecheckt.
|
|
Weitere Informationen bekommt man mit man gitignore
oder unter https://github.com/github/gitignore
findet man nützliche Beispiele.
Überprüfen der Änderungen
Bevor man seine Änderungen commited, empfiehlt es sich, diese nochmals zu überprüfen. Mit git status
sieht man, welche Dateien geändert wurden, jedoch nicht, was sich geändert hat. Dafür gibt es den Befehl git diff
:
|
|
git diff
vergleicht die Änderungen welche noch nicht gestaged wurden. Will man bereits gestagte Änderungen überprüfen braucht es zusätzlich das Flag --staged
oder --cached
(die beiden Flags sind Synonyme).
Commiten
Ist man sicher, dass man nur die Änderungen gestaged hat, welche man auch commiten will, kann man dies mit dem Befehl git commit
bewerkstelligen. Dadurch wird ein Editor geöffnet und man wird gebeten eine Beschreibung für die Änderungen anzugeben. Darüber was in eine “Commit Message” gehört, gibt es verschiedene Meinungen. Idealerweise probiert man sich vorzustellen, welche Informationen man braucht damit man die Änderungen die man gemacht hat zwei Jahre später immer noch versteht, mindestens aber was und warum das geändert wurde.
Ein paar hilfreiche Flags zu git commit
:
-m
um eine Message gleich anzugeben und nicht den Editor zu öffnen (kann je nach Commit Message Guideline hinderlich sein, da es keine Multiline Kommentare erlaubt):
|
|
-a
um alle editierten Dateien gleich mitzustagen. (Kurzform vongit add --all && git commit
) !ACHTUNG! kann gefährlich sein, da so schnell Änderungen in einen Commit rutschen, die nicht rein gehören!-v
um eingit diff --staged
im Editor angezeigt zu bekommen. So muss man sich nicht merken, was man eigentlich geändert hat und bekommt es beim schreiben der Commit Message noch einmal präsentiert.
WICHTIG: Es ist einiges einfacher Fehler vor dem Commiten als nach dem Commiten zu beheben, ein zweites mal über die Änderungen schauen ist sehr empfehlenswert!
Dateien löschen
Um eine Datei zu löschen, muss diese zuerst entfernt und dann gestaged werden, damit dies in der Git Datenbank ankommt. Um nicht zuerst rm foo
und dann git add foo
eingeben zu müssen, gibt es den Befehl git rm foo
. Will man eine bereits gestagte Datei aus der Versionsverwaltung jedoch nicht vom Filesystem löschen, weil man diese zum Beispiel im .gitignore
ergänzen möchte, dann kann man dies mit git rm --cached foo
erledigen.
WICHTIG: Jede Datei die irgendwann mal commited wurde ist für immer in der Git Geschichte und kann nur durch neu schreiben der selbigen wieder entfernt werden. Wer also zum Beispiel sein Passwort commited, weil dies in einer secret.yml
Datei steht, der sollte sich sofort bei einem 10x-Git-Profi-Engineer Hilfe holen.
Dateien Verschieben
Genauso wie löschen, muss auch beim Verschieben die Änderung Git mitgeteilt werden: mv README.md README && git rm README.md && git add README
oder in kurz und hübsch: git mv README.md README
.
Anzeigen der Commit Historie
Um die Geschichte eines Git Repositories anzuzeigen gibt es den Befehl git log
. Ohne Argumente zeigt git log
die Commits in umgekehrter chronologischer Reihenfolge, sprich jüngster Commit zuoberst. Pro Commit wird jeweils der Commit-Hash, der Name und Email Adresse des Authors, das Datum und die Commit-Message angezeigt. Um die effektiven Änderungen anzuzeigen gibt es das -p
oder --patch
Flag. Da der Output schnell gross wird und man wahrscheinlich auch nicht bis an den Ursprung der Geschichte zurück will, empfiehlt es sich die Anzahl Commits anzugeben. Will man zum Beispiel die letzten drei Commits anschauen macht man dies mit -3
. Oder man schränkt die Änderungen basierend auf die Zeit ein mit --since=
und --until=
ein (es werden die unterschiedlichsten Zeitangaben akzeptiert, am besten probiert man etwas aus. Bsp: --since=2.weeks
oder --until="2020-06-03"
). Auch mit --grep
oder --author
kann man die Resultate einschränken. Weitere Information liefert die Manpage man git log
und die Hilfefunktion git log -h
.
Änderungen rückgängig machen
Wo gehobelt wird fallen Späne, die meisten Schnitzer kann man jedoch selber wieder ausglätten. Am häufigsten committed man wohl zu schnell, hat eine Datei vergessen dazuzufügen oder hat sich bei der Commit Message vertan. Mit git commit --amend
kann man den letzten Commit editiern (genaugenommen nicht editieren. Man löscht ihn nur und erstellt eine korrigierte neue Version davon). Dies kann dazuführen, dass ein Remote den Commit nicht mehr annimmt, da die History nicht mehr übereinstimmt. Aber mehr dazu später.
Um eine gestagte Datei wieder zu modified (aber eben nicht gestaged) verschieben, kann man git reset HEAD <file>
verwenden. Um die Änderungen einer Datei rückgängig zu machen (also modified zu unmodified)
kann sie neu ausgecheckt werden mit git checkout -- <file>
. Achtung: Alle Änderungen seit dem letzten Commit gehen damit verloren!!! Wenn man sich an die beiden Befehle gerade mal nicht erinnert, dann kann man einfach ein git status
eingeben und den Hilfetext studieren 😉.
Mit Remotes arbeiten
Um mit anderen an einem Git-Projekt mitarbeiten zu können, braucht es Remotes, sprich eine Version des Projekts im Netzwerk, wo alle Beteiligten ihre Änderungen hin pushen und die Änderungen der Anderen pullen können.
Nachdem man ein Repo gecloned hat, sieht man ein Remote, man kann jedoch auch weitere definieren:
|
|
Wollen wir nun alle Information holen, welches das Zwiseli hat, jedoch noch nicht im Repo sind, kann man dies mit git fetch private
ausführen.
Fetching und Pulling
Es gibt zwei Arten, wie man Daten von einem Remote abholen kann, nachdem man das Repo gecloned hat.
git fetch <remote>
: holt alle Änderungen vom Remote seit dem letzten abholen und speichert die lokal. Wichtig zu beachten ist, dassgit fetch
die Änderungen nicht mit den lokalen Änderungen zusammenfügt, sondern dies manuell ausgeführt werden muss.git pull
: Wenn der lokale Branch mit einem remote Branch verknüpft ist, holtgit pull
die Änderungen dieses remotes und fügt sie gleich mit den Änderungen im lokalen Branch zusammen (merge). Was Branches sind und wie ein Merge funktioniert schauen wir uns in kürze an. Nur soviel: Wird ein Repo gecloned, wird der lokale sogenanntemaster
Branch mit demmaster
Branch desorigin
Remotes verknüpft.
Pushen
Wenn man seine Änderungen soweit hat, dass man sie mit dem Rest vom Team teilen will, dann kann man diese mit git push <remote> <branch>
auf den Server laden. Dies funktioniert jedoch nur, wenn man auf dem Server auch Schreibrechte hat und niemand anderes vor einem gepusht hat.