Durch meine Arbeit in verschiedenen Gruppen ist das Bedürfnis aufgekommen den beteiligten GIT näher zu bringen. Meine Sammlung an Informationen sowie Vorträge möchte ich in diesem Repository zusammen führen und zur freien Verfügung unter der CC-BY-4 online stellen.
Durch meine Arbeit in verschiedenen Gruppen ist das Bedürfnis aufgekommen den beteiligten GIT näher zu bringen. Meine Sammlung an Informationen sowie Vorträge möchte ich in diesem Repository zusammen führen und zur freien Verfügung unter der CC-BY-4 online stellen.
# Einführung in GIT
- Git ist eine Versionsverwaltung
- Funktioniert nicht bei Binärdateien
- Gut für Code, Text oder Vektorgrafiken
# Gitclient Einrichten
Mit dem Befehl ``cat ~/.gitconfig`` können wir uns die globalen Konfigurationen anzeigen lassen.
| Befehl | Bedeutung |
| ------ | --------- |
| ``git config --global color.ui true`` | Aktiviert eine farbige Ausgabe auf der Konsole. |
| ``git config --global user.name "Name der Angezeigt werden soll"`` | Setzt einen Nutzernamen |
| ``git config --global rebase.autosquash true`` | Führt bei ``git rebase`` automatisch ``git rebase --autosquash`` durch |
| ``git config --global pull.rebase true`` | Führt automatisch ``git pull --rebase`` aus wenn ``git pull`` ausgeführt wird. |
# Erste Schritte
## Das erste Repository
```{.bash}
mkdir MeineWebseite
cd MeineWebseite
# Initialisieren des Repositorys
git init
# Status Ausgeben
git status
```
## Erster Commit
*HTML5Boilerplate in den neuen Ordner kopieren*
```{.bash}
git status
git add css
git status
git add js/main.js
git status
```
Für eine kürzere Statusausgabe: ``git status -s``, dabei steht ``>A<`` für Added, ``>??<`` für nicht beobachtete Dateien und ``> M<`` ``>M <`` veränderte Datei im und nicht im Statigbereich.
```{.bash}
git add -A # Alles hinzufügen
git commit -m "HTML 5 Boilerplate hinzugefügt"
git status
```
## Das Log
Mit hilfe von ``git log`` können wir uns nun das log ausgeben lassen.
| commit-id (kurz - lang) | Sie ist eine SHA-1-Checksumme, sie ist eindeutig und wird zur genauen Identifizierung eines Commits benötigt. |
| HEAD | Aktueller stand |
| master~2 | voletzter Commit auf master |
# Neue Version
Wir ändern die ``index.html`` Datei.
```{.bash}
git status
git diff
git add index.html
git commit -m "Neue Überschrift"
git log
```
Für eine divitilere auswahl der hinzuzufügenden Zeilen einer Datei kann man mit ``git add -p`` nur einzelne parts hinzufügen.
Da ``git diff`` nur die Änderungen zwischen dem aktuellen Ordner und dem letzten Commit ohne den Dateien im Stagingbereich anzeigt, gibt es noch die befehle ``git diff --staged`` und ``git diff --cached``.
## Mehrere Änderungen in einem Commit
Wir ändern die ``index.html`` und die README Datei.
```{.bash}
git status
git commit -a -m "Namensgebung"
```
Die Größe von Commmits sollten immer nur so klein wie möglich und so groß wie nötig sein. Wenn Sie in Projekten wie dieser statischen Webseite arbeiten, dann sollten Sie zum Beispiel Inhalte auf Unterseiten nur dann in einen Commit zusammenfassen, wenn diese strikt zusammengehören! Das Stichwort ist "Logische Änderungen".
HEAD = der HEAD ist immer der aktuelle Stand des branches in dem man sich befindet.
## Dateien Umbenennen
Mit ``git mv alteDatei neueDatei`` gibt es ein Befehl der Dateien verschiebt/umbenennt mit dem wissen von Git.
```{.bash}
mv alteDatei neueDatei
git add neueDatei
git rm alteDatei
```
Mit ``git log --follow neueDatei`` lassen sich die Änderungen an einer Datei auch dann verfolgen, wenn diese Umbenannt wurde.
## Änderungen rückgängig machen
#### revert
``git revert <commit-id>`` erzeugt einen neuen Commit der einen alten rückgängig macht. Die Commitmassage sollte hier nicht geändert werden damit die übersichtlichkeit gewahrt bleibt.
Die Funktion ist geeignet für einen Commit der schon veröffentlicht wurde und an dem mehrere Entwickler arbeiten.
> ändern der Index.html, commiten und reverten! Danach machen wir ein Reset.
#### reset
``git reset ``
| Modus | Verhaltensweise | Änderungen |
| ----- | --------------- | ---------- |
| soft | Hierdurch bleibt die Änderung erhalten und im Stagingbereich. Sinvoll wenn noch weitere Änderungen in den letzten Commit fließen sollten. | Staging |
| mixed (default) | Die änderung bleibt erhalten ist jedoch nicht im Statingbereich | Arbeitsverzeichnis |
| hard | Die Änderungen gehen verloren und der Ordner auf den zurückgesetzten Commit gebracht.| Nirvana |
```{.bash}
git reset HEAD~2 %um die letzten beiden Commits rückgängig zu machen
git status
# Zeile in Index.html anfügen und commiten
git reset --soft HEAD~1
git status
# Index.html commiten
git reset HEAD~1
git status
# Index.html commiten
git reset --hard HEAD~1
git status
cat index.html
```
### interaktives rebase
KOMMT NOCH!!
## Hinter den Kulissen
Git speichert Änderungen als Snapshots, nicht als Diffs. Es ist zu beachten das Git lediglich neue Dateien aufnehmen kann, das bedeutet das gelöschte Dateien in der Historie trotzdem noch vorhanden sind. **Vorsicht** bei Passwörtern und anderen sicherheitsrelevanten Daten. Hierzu gibt es die .gitignore Datei auf die wir gleich zurück kommen!
Außerdem Versioniert Git nur Dateien weswegen leere Ordner nicht mit aufgenommen werden. Sobald der Ordner eine Datei enthält, wird dieser auch mit aufgenommen.
Zur genauen Arbeit sei das Kapitel 2.7 aus dem Buch Versionsverwaltung mit Git von "Unaussprechlich" empfohlen.
# Arbeiten mit Branches
Branches sind Zeiger auf Commits.
```{.bash}
git branch
git branch feature/navigation
git branch feature/content
git checkout feature/navigation
# Navigation hinzufügen und commit ausführen
git checkout master
git merge feature/navigation
# Fast-Forward Merge
```
> Fast-Forward Merge (3.3 Branches mergen)
```{.bash}
git checkout feature/content
# content hinzufügen und commiten
git checkout master
git merge feature/content
# merge massage bestätigen (wird in der Regel so belassen)
git log -n 2
# Zeile Merge mit den verweisen auf die beiden vorgänger Commits
```
> Der diff eines Merge-Commits ist grundsätzlich leer und verweist auf die beiden vorgänger Commits aus denen er hervorgegangen ist.
## Merge Konflikte
Wir erstellen einen Mergekonflikt
```{.bash}
git checkout master
git checkout -b title
# Title ändern zu "Hallo Mergekonflikt"
# commit -m "Titel für Mergekonflikt"
```
```{.bash}
git checkout master
# Titel ändern in "Neuer Titel"
# commit -m "Neue Überschrift"
git merge title
```
Nun haben wir einen Mergekonflikt.
```{.html}
<<<<<<<HEAD
<h1>Hallo!</h1>
=======
<h1>Hallo Merge-Konflikt!</h1>
>>>>>>> title
```
Zur Behebung werden die Marker gelöscht und die Zeile die beibehalten werden soll übernommen.
```{.bash}
git add index.html
git status # Zeigt das alle Konflikte behoben wurden
git commit
git log -p # Zeigt alle änderungen an
git log --oneline
# Trotz Mergekonflikt sind beide Commits in der History gelandet!
# Der Merge Commit ist trotz des Konfliktes leer!
```
## Mergetool
```{.bash}
git mergetool --tool=kdiff3 #Nur unter Linux!
```
| Bezeichnung | Stand |
| ----------- | ------ |
| A | Stand bevor title gemerged wurde |
| B | Ist die Lokale Datei in dem der Konflikt vorliegt |
| C | Ist die Datei aus title die gemerged werden soll |
## Rebase (3.7)
Um Konflikten aus dem Weg zu gehen und eine saubere History zu erzeugen ist ein Rebase sinvoll. Hierbei werden Commits aus anderen Branches übernommen ohne einen Merge durchführen zu müssen.
```{.bash}
# Benötigt werden zwei Commits auf unterschiedlichen branches!
git checkout -b fix/more_content master
# änderung der Index.html
git checkout master
# Navigation erweitern!
git checkout fix/more_content
git rebase master
git checkout master
git merge fix/more_content --no-ff
# Mit --no-ff wird ein Merge-Commit angelegt und kein Fast-Forward Merge,
# damit kann man die existenz des Branches in der History nachvollziehen.
# Dies ist gerade bei großen Projekten oder Teams sinvoll und hilfreich.
```
> Nun wurde ein Fast-Forward Merge erzeugt und die History ist sauber und ohne Merge!
```{.bash}
git log -n 3
```
# Github!
Etwas durchklicken und bekannt machen. Gitlab und Gogs/Gitea zeigen. Und dann zu den Entfernten Repositories gehen.
# Entfernte Repositories
## Remoterepository erstellen
```{.bash}
mkdir ~/git
git clone --bare . ~/git/meineWebseite.git
```
``git clone`` mit dem Parameter ``--bare`` klont, also kopiert das ganze Repository aus dem aktuellen Verzeichnis in das Verzeichnis ``~/git/meineWebseite.git``
```{.bash}
# Remote-Repository hinzufügen
git remote add origin ~/git/meineWebseite.git
git remote # Auflisten der Repositories
git fetch # Abholen der Daten aus dem Remote-Repository
```
**Origin** ist hierbei die Bezeichnung des Remoterepositories. Es ist möglich mehrere Remoterepositories an zu legen und zu verwalten. Die Branches des Remote Repositories fangen mit origin an, da dies der Name des Remotes ist.
Die Änderungen im Remote müssen mit ``git merge origin/master`` in den eigenen Master übernommen werden. Hierbei kann es zu Mergekonflikten kommen. ``git pull origin master`` ist eine Kombination aus ``fetch`` und ``merge``.
```{.bash)
git branch # Zeigt nur die eigenen Branches
git branch -a # Zeigt auch die Branches aus dem Remote - trotz beginn mit remote lassen sie sich ohne diesen auschecken!
#änderungen im master anlegen und commiten
git status # Zeigt das man 1 vor origin/master ist!
git push # Fehlermeldung
git push --set-upstream origin master
git push # Alles aktuell!!
```
## Löschen von Branches
```{.bash}
git checkout master
git branch --merged # Zeigt die Branches die nach HEAD (master) gemerged sind!
git branch --no-merged <branch> # Umgekehrt zu --merged
git branch -a --merged master # Zeigt auch die remots an!
```
``git branch -d <branch>`` ist die Sichere Methode, mit ``git branch -D <branch>`` wird immer gelöscht, was zu Datenverlust führen kann. Auswirkung jedoch nur auf die lokalen Repositories.
```{.bash}
git push origin --delete <branch> # löscht auf dem entfernten
git push origin :<branch> # kurzform von --delete
```
# Befehlsliste
| Befehl | Bedeutung |
| ------ | --------- |
| git log --pretty=oneline | Gibt den Log in einzeilern aus |
# Weiterführende Informationen
## Literatur
* Buchtipp: Versionsverwaltung mit Git von Vijayakumaran, Sujeevan
* [Become a git guru](https://www.atlassian.com/git/tutorials)
## Interaktive Tutorials
* [Try Git von Github](https://try.github.io/levels/1/challenges/1)
* [Tutorial von rogerdudler](https://rogerdudler.github.io/git-guide/index.de.html)
## Videos
* Vortrag: [ Nicht alltägliche Git-Funktionen ](https://media.ccc.de/v/froscon2017-1919-nicht_alltagliche_git-funktionen)
* [fournova](https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=14&ved=0ahUKEwjz6ZCQr5HaAhXFPZoKHXo0A7cQFgigATAN&url=https%3A%2F%2Frhoenerlebnis.de%2F_upl%2Fde%2F_pdf-seite%2Fgit_cheatsheet_de_white.pdf&usg=AOvVaw0yb6eHfutNKvJ6eWf05tqm) auf deutsch mit guten Hinweisen!