Git Seminar¶
(Wer sofort mit den Git Seminarunterlagen loslegen will: Einführung)

Git Website Screenshot 2023¶
Mit den Beschreibungen auf der Git Website hat man schon einen guten ersten Eindruck von Git.
Git ist eine Freie, offene und kostenlose Software für die Versionskontrolle von Dokumenten in einer verteilten (distributed) Struktur. Dabei ist Git sicher und schnell.
Sicher meint, dass die in das System eingecheckten Daten durch Signaturen nachvollziehbar unverändert wieder entnommen werden können. Veränderungen an den Daten sind jederzeit erkennbar und nachvollziehbar.
Große Teile der aktuellen Linux Kernel Entwicklungen werden mit Git abgewickelt, sodass man von professioneller Performance selbst unter größter Last sprechen kann.
Für mich hat sich Git - oft in Kombination mit geeigneten Dokumentformaten (siehe reStructuredText) - zum täglichen Werkzeug für die unterschiedlichsten Aufgaben und Lösungen entwickelt.
Ich wünsche uns viel Spaß bei der professionellen Umsetzung von Projekten mit Git..
Ihr Trainer Joe Brandes
Hier geht es zum Stichwortverzeichnis …
Einführung¶
Die vorliegenden Unterlagen zum Seminar Git von Joe Brandes beziehen sich auf aktuelle Versionen für Windows und Linux. Aber natürlich handelt es sich auch bei Git um sehr aktive Entwicklergemeinschaften.

Dateien im Verlauf eines Projekts (Quelle: Pro Git Book - Was ist Git? )¶
Die Visualisierung stammt aus öffentlichen Pro Git Book (siehe Literatur). Hinweis zum Verständnis: gestrichelte Objekte sind unverändert.
Ein paar technische Eigenschaften zu Git:
Dezentrales Versions Controll System (VCS)
Open-Source für unterschiedliche OS-Plattformen
Integrität (SHA-1 Hashes) der Daten (allgemein: Doks - nicht nur Texte)
Performance für klein(ste) und große Projekte
Alle Arbeiten lokal möglich
Diese Auflistung stellt die besondere Zielrichtung bei den Überlegungen für eine neue Versionierungstechnik bei Entwickler Linus Torvalds dar.
Wichtig für das Grundverständnis und Funny
Git speichert Snapshots - also nicht etwa Änderungen (Abweichungen, Diffs) wie andere Systeme.
Git ist englisch (britisch) für Blödmann, Depp oder auch Idiot - typisch Linus Torvalds.
Git Software¶
Wir starten mit ein paar einführenden Infos/Links:
Idee zu Git: Linus Torvalds (Grund: Umstieg von Software BitKeeper)
Maintainer: Junio C. Hamano
Hauptquelle Git Portal
Erläuterungen zu SCM : Software Configuration Managenment
Technische Basis in meinen Seminaren: Git for Windows und Git (Linux).
Die unterschiedlichen Installationen in und für die unterschiedlichen Betriebssysteme sind grundsätzlich gut dokumentiert. Bei Linux-Installationen beachte man bitte die zur Verfügung gestellten Versionen der unterschiedlichen Installations-Repositories.
Git für Windows¶
Bereitstellung der Software Git für Windows
Download: Aktuelle Git für Windows Version
Winget:
winget install --id Git.Git
Als Standard installieren wir die 64-Bit-Variante. Es gibt auch portable Varianten. Die Installation findet User-Bereich eines Windows-Accounts statt, wenn man nicht ausdrücklich mit Admin-Rechten installiert!

Installation Git for Windows¶
Für die Unterstützung einer inuxoiden Entwicklungsumgebung und der entsprechenden CLI-Tools installieren wir uns die entsprechende Unterstützung.

Optionale Linux-Tools¶
Die kompletten Installationsschritte werden (zumeist) im Seminar begleitet und diskutiert/analysiert.
Git für Linux¶
Wir nutzen für eine Seminarumgebung beispielsweise:
Installationen Bare-Metal
Linux VMs (per Hyper-V, ProxmoxVE)
WSL2 Windows Subsystem Linux - eine Linux Plattform integriert in Windows
Für die Bereitstellung der Git-Software in der gewählten Distribution sollte man die Aktualität der bereitgestellten Software-Version beachten.
Für alle Standard-Distros existieren geeignete Anleitungen.
Konfiguration¶
Wir analysieren erst einmal unsere Git-Version:
$ git --version
git version 2.22.0.windows.1
Hier wurde der Parameter --version
benutzt - es sollte auch der
Subbefehl version funktionieren: git version
.
Wir lassen uns als Nächstes die Konfigurationsumgebung für Git auflisten:
$ git config --list
core.symlinks=false
core.autocrlf=true
core.fscache=true
...
rebase.autosquash=true
http.sslcainfo=C:/Users/joeb/AppData/Local/Programs/Git/mingw64/ssl/certs/ca-bundle.crt
http.sslbackend=openssl
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
credential.helper=manager
...
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
...
Und da sich die ergebende Konfiguration aus einer Kombination verschiedender Konfigurationsorte zusammensetzen kann, lassen wir uns diese Konfigurationen mit auflisten.
$ git config --list --show-origin
file:"C:\\ProgramData/Git/config" core.symlinks=false
file:"C:\\ProgramData/Git/config" core.autocrlf=true
file:"C:\\ProgramData/Git/config" core.fscache=true
...
file:"C:\\ProgramData/Git/config" rebase.autosquash=true
file:C:/Users/joeb/AppData/Local/Programs/Git/mingw64/etc/gitconfig http.sslcainfo=C:/Users/joeb/AppData/Local/Programs/Git/mingw64/ssl/certs/ca-bundle.crt
file:C:/Users/joeb/AppData/Local/Programs/Git/mingw64/etc/gitconfig http.sslbackend=openssl
file:C:/Users/joeb/AppData/Local/Programs/Git/mingw64/etc/gitconfig diff.astextplain.textconv=astextplain
file:C:/Users/joeb/AppData/Local/Programs/Git/mingw64/etc/gitconfig filter.lfs.clean=git-lfs clean -- %f
file:C:/Users/joeb/AppData/Local/Programs/Git/mingw64/etc/gitconfig filter.lfs.smudge=git-lfs smudge -- %f
file:C:/Users/joeb/AppData/Local/Programs/Git/mingw64/etc/gitconfig filter.lfs.process=git-lfs filter-process
file:C:/Users/joeb/AppData/Local/Programs/Git/mingw64/etc/gitconfig filter.lfs.required=true
file:C:/Users/joeb/AppData/Local/Programs/Git/mingw64/etc/gitconfig credential.helper=manager
...
file:.git/config core.repositoryformatversion=0
file:.git/config core.filemode=false
file:.git/config core.bare=false
file:.git/config core.logallrefupdates=true
file:.git/config core.symlinks=false
file:.git/config core.ignorecase=true
...
Erkenntnis: es gibt also - wie eigentlich immer - mehrere Konfigurationsdateien, die dann letztlich die aktuelle Gesamtkonfiguration ergeben.
Hinweis
Manche Einträge - siehe core.symlinks - mehrfach! Dann setzt sich die letzte bzw. projektnächste Konfiguration durch.
Erläuterungen hierzu kann man auf der Dokumentationsplattform auf git-scm-Portal im Abschnitt FILES nachlesen und vertiefen.
Allgemeine Übersicht zu Konfigurationsquellen:
Systemweit
Benutzer
Repo
Worktree (wenn präsent/genutzt)
Und die Pfade sind natürlich nach Betriebssystem abweichend und
insbesondere bei Windows sollte die Nutzung der /
besonders
beachtet werden.
Inbetriebnahme¶
Es sollten unbedingt gleich zwei user Konfigurationen für die global Umgebung (Scope) erstellt werden. Global heißt hier, das diese Benutzerdaten/Konfigurationen für diesen Benutzer und alle seine Git-Projekte gelten!
Ordner/Dateipfad: ~/.gitconfig (also Home-Dir des Users)
$ git config --global user.name "Max Mustermann"
$ git config --global user.email "max.mustermann@example.com"
# Standardzweig für neue Git Repos auf main (statt master)
$ git config --global init.defaultBranch main
Beachten: keinerlei Gleichheitszeichen! Danach bitte unbedingt die Daten wieder in der Gesamtkonfiguration checken.
Hinweis
Es lassen sich noch viele weitere Konfigurationen festlegen. Am einfachsten bitte später die git config-Hilfen (z.B. git help config) beachten oder einfach die Vervollständigung von Befehlen mit Tab nutzen.
Mit git help -c
bzw. git help --config
lassen sich alle verfügbaren Konfigurationsparameter auflisten.
Oder aber online unter Git config - Variables inklusive Erläuterungen.
Für die Anzeige einer aktuellen, einzelnen Konfiguration nutzt man
$ git config user.name
$ git config --show-origin user.email
Der Schalter --show-origin
zeigt die Quellen für die jeweilige
Konfiguration mit an.
Eine einfache Übersicht aller Konfigurationen erhält man mit git help -c
.
Für viele weitere Einstellungen siehe Erste Schritte - Git Basis-Konfiguration aus dem Pro Git Online Buch.
Klassische Grundeinstellung für gemischte (Linux/Mac vs. Windows OS) Umgebungen:
In lokaler Git Config: git config --global core.autocrlf true
und in
Repository in Datei .gitattributes
die Zeile * text=auto
einfügen.
Anmerkung / Empfehlung: in aktuellen hetereogen Umgebungen mit professionellen Tools zum Editieren und zur Git-Nutzung keine Probleme mehr auffällig. Und am Besten nutzt man als Entwickler unter Windows einfach die WSL2!
Siehe Sujeevan Vijayakumaran - Vortrag GPN19 (Zeit: 33:30)
Weitere Beispiele für Konfigurationen folgen.
Extra / Grep Spielerei!
Bei Recherchen zu Git Configs bin ich über die folgende sehr spezielle Möglichkeit gestolpert sich die möglichen Konfigurationsparameter auflisten und erklären zu lassen.
Stackoverflow Thread to git config: list all variables
Git Master Branch curlen und Ordner Documentation entpacken
curl -L https://api.github.com/repos/git/git/tarball/master | tar -xvzf- --wildcards "*/Documentation/*"
Wir erhalten eine Compact Version with Grep Magic:
grep --recursive \ --binary-files=without-match \ --no-filename \ --only-matching \ --perl-regexp \ --null-data \ --regexp='(?ms)(?:^[a-zA-Z0-9]{2,}\.[<>()*.a-zA-Z -]+::\v+)+?(?:(?:\v|\h+\V+\v))+(?:\v|\Z)'
Eine noch detailliertere Version mit:
... --regexp='(?ms)(?:^[a-zA-Z0-9]{2,}\.[<>()*.a-zA-Z -]+::\v+)+?(?:\v|\h+\V+\v)+(?:\+\v+(?:--\v+.+?--|[^+]\V+(?!::\v))+)*(?:\v|\Z)'
Solche Spielereien wie immer und elbstverständlich ohne Gewähr ;-) [Status: zuletzt getestet Sep/2023].
Git 101¶
Für das Verständnis der Arbeit mit Git muss man die unterschiedlichen Zustände (gerne auch Orte) kennen.

Stages - die unterschiedlichen Zustände unserer Daten¶
Wir beginne mit den folgenden States für Git:
Working Directory - Arbeitsverzeichnis für Modifikationen an Dokumenten
Staging Area - auch als Index bezeichnet
.git directory - das lokale Repository
Anm.: später kommen noch der Stash und (Öffentliche) Repositories hinzu.
Hilfe in Git¶
Git bietet Hilfe mit verschiedener Syntax.
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
Letzteres Kommando bezieht sich natürlich auf Linux-Manpages und ist
in einer reinen Windows-Umgebung nicht verfügbar.
Es folgt ein Beispiel für git commit
.
GIT-COMMIT(1) Git Manual GIT-COMMIT(1)
NAME
git-commit - Record changes to the repository
SYNOPSIS
git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]
[--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>)]
[-F <file> | -m <msg>] [--reset-author] [--allow-empty]
[--allow-empty-message] [--no-verify] [-e] [--author=<author>]
[--date=<date>] [--cleanup=<mode>] [--[no-]status]
[-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
[(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]
[--] [<pathspec>...]
DESCRIPTION
Create a new commit containing the current contents of the index and the given log message describing the changes.
The new commit is a direct child of HEAD, usually the tip of the current branch, and the branch is updated to
point to it (unless no branch is associated with the working tree, in which case HEAD is "detached" as described
in git-checkout(1)).
The content to be committed can be specified in several ways:
1. by using git-add(1) to incrementally "add" changes to the index before using the commit command (Note: even
modified files must be "added");
2. by using git-rm(1) to remove files from the working tree and the index, again before using the commit command;
3. by listing files as arguments to the commit command (without --interactive or --patch switch), in which case
Manual page git-commit(1) line 1 (press h for help or q to quit)
Auf Windows-Systemen mit MingW64-Installationen für Git werden die lokalen HTML-Hilfe-Seiten ausgeliefert.
Starten mit Git¶
Es gibt verschiedene Wege ein Git Repository zu erhalten.
git init
- Arbeitsverzeichnis wird ein Git Repogit clone
Bestehendes Repository (z.B. online), das wir auf unser System clonen (git clone …)
Hinweis
Das Clonen erzeugt - ohne zusätzliche Parameter - einen neuen Unterordner!
Im Grunde ist es Git egal auf welchen Ordnerstrukturen es arbeitet, aber wir haben es gern ordentlich. Daher erstellen wir im Documents-Ordner einen Ordner git-projekte:
Windows:
C:\Users\username\Documents\git-projekte
Linux:
/home/username/Documents/git-projekte
Die verschiedenen Schrägstriche sind in modernen Konsolen bei den Eingaben häufig auch nur als einfache Schrägstriche verwendbar. In Konfigurationsdateien ist besondere Sorgfalt auf die Schrägstriche zu legen. Bei Windows-Systemen sind manchmal sogar doppelte Schrägstriche statt Backslash nötig. Hierzu folgen in Seminaren entsprechende Übungen.
Zusammenfassung: ein Ordner wird zu einem Git-Projekt, indem mit einem (verstecktem) Ordner .git das Git-System die Überwachung/Protokollierung der Objekte beginnt.
Lebenszyklen¶
Grundsätzlich hat jede Datei (jedes Objekt) im Arbeitsverzeichnis zwei Grund-Zustände:
Tracked - Datei befindet sich in der Staging Area (Index) und ist Git bekannt
Untracked - Datei liegt einfach nur im Arbeitsverzeichnis und ist Git unbekannt
Wenn man die Zustände (hier: Tracked) genauer aufsplittet kann folgende Zustände und Aktionen erkennen:

Lebenszyklen von verfolgten/unverfolgten Git-Inhalten¶
Bitte genauer analysieren und verstehen. Hierfür benötigen wir das
Git-Kommando git status
.
Git Status in Kurzdarstellung (Short)
Für das Git-Kommando git status
gibt es die kurze
Ausgabevariante git status --short
oder git status -s
.
Es folgt eine beispielhafte Ausgabe - beachten: (2-Spalter für die Kennzeichnungen)
Spalte 1: Staging Area / Index
Spalte 2: Working Directory / Arbeitsverzeichnis
Beispielhafte Ausgabe:
$ git status -s
M README # geändert im Index
MM Rakefile # geändert - dann add-ed to Index und dort geändert
A lib/git.rb # neue Datei im Index
M lib/simplegit.rb # geändert im Index
?? LICENSE.txt # neue Datei nur im Arbeitsverzeichnis
Kennungen in den Spalten:
? - not tracked / unbekannt
M - Modified / geändert
A - Added / hinzugefügt
Für weitere Infos siehe Git Dokumentation zu Status Ausgaben.
EMPTY = unmodified
M = modified
T = file type changed (regular file, symbolic link or submodule)
A = added
D = deleted
R = renamed
C = copied (if config option status.renames is set to „copies“)
U = updated but unmerged
Beim Einstieg in Git lohnt sich eine ständige Sicht auf den Status der Git-Dokumente.
.gitignore¶
Im einfachsten Fall liegt die .gitignore
im Hauptverzeichnis
des Git-Projekts. Man kann aber auch in Unterordnern eigene .gitignore
anlegen, die dann in diesen Ordnern gelten.
Hinweis
Der Linux Kernel hat Hunderte von kommentierten .gitignore Files!
Für genauere Nutzung bitte einfach die verschiedenen Git-Dokumentation nutzen:
Es gibt also diverse aufwendige Vorlagen/Templates für diverse Entwicklungsumgebungen (z.B. Python, Java, …).
Hier eine einfache Beispieldatei (aus dem Pro Git Book):
# ignore all .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
/TODO
# ignore all files in any directory named build
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf
Eine kleine .gitignore für unsere Übungsumgebungen könnte z. B. so aussehen:
$ cat .gitignore
# folder for Builds
_build/
# Dolphin
.directory
# VSCode Settings
.vscode/
# lokale, persönliche Datei
localinfos.txt
Hier wird ein gesamter Ordner _build
, alle Dateien .directory
,
die Settings von Microsoft Visual Studio Code
und eine (spätere) Übungsdatei localinfos.txt
von Git ignoriert.
Wenn diese Datei erstellt wurde sieht man mit git status
: (hier Auszug)
...
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
Diese Datei muss also - wie jede Andere - noch Git mitgeteilt (commited) werden. In den späteren Auszügen wird die .gitignore einfach weggelassen - sie wird ja auch nicht dauernd geändert und taucht somit nicht im Index auf.
Tipp
Zuerst .gitignore
erstellen, add-en und commit-en -
und danach die entsprechenden Dateien und Ordnerstrukturen.
Nicht ohne Grund kann man auf GitHub direkt beim Erstellen
neuer Repositories diese Datei direkt erzeugen lassen.
Testweise kann man später die Ausschlussdatei localinfos.txt
erstellen und schauen, was passiert.
Und natürlich lassen sich später auch Dateien/Ordner aus dem Repository wieder löschen.
Es gibt neben der .gitignore
auch noch andere Exclude
Mechanismen, die der Beitrag
Red Hat - How to ignore files in Git without .gitignore
beschreibt.
Index (Staging Area)¶
Übungen: Beispielhafte Vorgehensweisen - soweit nicht anders erwähnt - starten wir im Ordner git-projekte.
Wir nutzen im folgenden linuxoide Befehle in der Git Bash von Git for Windows:
Ausgangssituation: (Befehle: pwd
, ls -al
)
$ pwd
/c/Users/joeb/Documents/git-projekte
$ ls -al
total 4
drwxr-xr-x 1 joeb 197121 0 Jul 9 18:39 ./
drwxr-xr-x 1 joeb 197121 0 Jul 10 15:20 ../
Ordner erstellen und in Ordner gehen: (Befehle: mkdir
, cd
)
$ mkdir testing
$ cd testing
$ pwd
/c/Users/joeb/Documents/git-projekte/testing
$ ls -al
total 4
drwxr-xr-x 1 joeb 197121 0 Jul 10 19:17 ./
drwxr-xr-x 1 joeb 197121 0 Jul 10 19:17 ../
Git Repository initialisieren: git init
$ git init
Initialized empty Git repository in C:/Users/joeb/Documents/git-projekte/testing/.git/
$ ls -al
total 8
drwxr-xr-x 1 joeb 197121 0 Jul 10 19:19 ./
drwxr-xr-x 1 joeb 197121 0 Jul 10 19:17 ../
drwxr-xr-x 1 joeb 197121 0 Jul 10 19:19 .git/
Es folgt ein entstandenes leere Git-Repo als Baum.
Wir nutzen das PowerShell-Cmdlet Show-Tree
aus Modul PSCX. Solche
Installationen werden in meinen Seminaren für die PowerShell fertig als
Git-Repo-WindowsPowerShell-Profile genutzt.
PS C:\Users\joeb\Documents\git-projekte\testing> Show-Tree -ShowLeaf -Force
C:\Users\joeb\Documents\git-projekte\testing
└──.git
├──hooks
│ ├──applypatch-msg.sample
│ ├──commit-msg.sample
│ ├──fsmonitor-watchman.sample
│ ├──post-update.sample
│ ├──pre-applypatch.sample
│ ├──pre-commit.sample
│ ├──pre-push.sample
│ ├──pre-rebase.sample
│ ├──pre-receive.sample
│ ├──prepare-commit-msg.sample
│ └──update.sample
├──info
│ └──exclude
├──objects
│ ├──info
│ └──pack
├──refs
│ ├──heads
│ └──tags
├──config
├──description
└──HEAD
Wir rufen den ersten Status für das Git-Projekt ab: git status
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
Oder in Kurzform mit git status -s
bzw. als git status --short
, was hier (natürlich) nichts ausgiebt.
Dann erstellen wir mal eine erste Datei testdatei.txt
: (Befehle: touch
, echo
mit Umleitung, cat
)
$ echo "Zeile 1" > testdatei.txt
$ cat testdatei.txt
Zeile 1
Und jetzt haben wir einen neuen Git Status:
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
testdatei.txt
nothing added to commit but untracked files present (use "git add" to track)
$ git status -s
?? testdatei.txt
Git erkennt also eine untracked Datei: testdatei.txt.
Damit Git diese Datei verarbeiten kann, muss diese Datei
in den Index / Staged Area: git add
$ git add testdatei.txt
warning: LF will be replaced by CRLF in testdatei.txt.
The file will have its original line endings in your working directory
Hinweis
Statt git add
konnte man (früher) auch das Synonym git stage
nutzen!
Normalerweise findet man keine Rückmeldung mit git add. Es könnte allerdings auf unterschiedliche Modi für Zeilenwechsel hingewiesen werden:
Unix/Linux: nur Line Feed (LF)
Windows: Carriage Return & Line Feed (CRLF)
Aus diesem Grund erhalten Windows-User beim Öffnen von Textdateien aus dem Netz häufig einzeilige Texte im Windows Notepad (Windows Standard: Editor).
Falls Probleme auftauchen in gemischten Entwicklungsumgebungen, bitte die folgenden Konfigurationen beachten:
core.eol
core.safecrlf
core.autocrlf
Literatur: s. Das Git Buch - gitbu.ch, Kapitel 1.3.4 „Zeilenenden einstellen“
Aktuellen Git Status abrufen:
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: testdatei.txt
Wir haben die Datei gestaged - sie befindet sich jetzt in der Staged Area - dem Index.
Jetzt erstellen wir eine zweite Datei testdatei2.txt
mit Befehl touch
und dann mit ordentlichem Editor (z.B. Notepad++, Visual Studio Code
oder auch VIm/Neovim) bearbeiten.
$ touch testdatei2.txt
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: testdatei.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
testdatei2.txt
Auch wieder die neue Datei stagen - also dem Index hinzufügen: git add
$ git add testdatei2.txt
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: testdatei.txt
new file: testdatei2.txt
Jetzt befinden sich beide Dateien im Index von Git.
Wir ändern eine Datei - hier: testdatei.txt
- und fügen neuen Text ein!
Das führt zum aktuellen Status:
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: testdatei.txt
new file: testdatei2.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: testdatei.txt
Wir sehen, dass es die Datei testdatei.txt
quasi zweimal gibt:
in der Staging Area und
als modifizierte Dateiversion, die wieder ge-add-ed werden muss
Also: git add
für die Datei und wieder Status analysieren:
$ git add testdatei.txt
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: testdatei.txt
new file: testdatei2.txt
Alles wieder aktuell im Index (alt. Bez.: Staging Area).
Um unsere Arbeiten jetzt in das Git Repository einschecken zu können, müssen wir ein git commit durchführen. Hierfür sollten wir aber zuerst Anweisungen hinterlegen, welchen Dateien/Ordner ausgeschlossen sein sollen.
Tipp
For dem ersten Commit bitte die .gitignore
erstellen.
Erster Commit¶
Wenn wir jetzt den aktuellen Projektzustand in der Git Repository
einchecken wollen, so benötigen wir den Befehl git commit
.
Der lokale Ordner .git
in unserem Projektordner stellt das Git-Repo dar.
Achtung
Sollten Sie beim Committen den Parameter -m
für die Commit-Message vergessen,
so landen Sie im VI und müssen mittels i
in den Einfügemodus zum Schreiben.
Danach mit ESC
und ZZ
die Bearbeitung beenden.
Besser: mit Parameter -m
arbeiten oder anderen Standard-Editor
konfigurieren.
Best Practise für Commits
früh und häufig commiten (Änderungen einchecken)
eine logische/inhaltliche Änderung entspricht einem Commit
Commits lassen sich später zusammenfassen / aufräumen (siehe rebase)
Und los geht es:
$ git commit -m 'Initial commit; First Commit to .git'
[master (root-commit) 636908f] Initial commit; First Commit to .git
2 files changed, 4 insertions(+)
create mode 100644 testdatei.txt
create mode 100644 testdatei2.txt
Man erkennt den aktuellen Branch mit Standardname master und die Quittung root-commit - also die Wurzel für alle weiteren Arbeiten/Änderungen am Git-Repo.
Der Commit ist mit einer eindeutigen (hier abgekürzten) SHA-1-Summe gekennzeichnet: 636908f
Der Commit kann mit git show
dargestellt werden:
$ git show
commit 636908f2b795b68c4c99f978239be5e274bfea05 (HEAD -> master)
Author: Joe Brandes <joe.trainer@example.com>
Date: Thu Jul 11 14:04:11 2019 +0200
Initial commit; First Commit to .git
diff --git a/testdatei.txt b/testdatei.txt
new file mode 100644
index 0000000..2fddc57
--- /dev/null
+++ b/testdatei.txt
@@ -0,0 +1,3 @@
+Zeile 1
+Zeile 2
+
diff --git a/testdatei2.txt b/testdatei2.txt
new file mode 100644
index 0000000..a33806c
--- /dev/null
+++ b/testdatei2.txt
@@ -0,0 +1 @@
+Text in Datei 2
Spätestens jetzt ist deutlich zu erkennen: ein Commit ist hier eine Zustandsbeschreibung von mehreren Dateien. Für jede Datei ist natürlich der Diff (die Änderung) beschrieben.
Eine Analyse für das Git-Projekt zeigt jetzt:
$ git status
On branch master
nothing to commit, working tree clean
Alle Dateien besitzen jetzt (wieder) den Status Unmodified, was eben mit keinem Kürzel / keiner Anmerkung bedacht wird.
Tipp
Man kann das git add ...
auch mit git commit -a -m '...'
zu einem Schritt vereinen. Allerdings werden dann wirklich alle getrackten,
veränderten Dateien in einem Schritt commited. Damit könnte man auch
ungewünschte Änderungen/Dateien ins Git Repo veröffentlichen.
Wir werden erst einmal immer einzeln den Git Status beobachten
und sauber mit git add
gefolgt von git commit
arbeiten.
Daten ändern¶
Was passiert jetzt, wenn wir die Dateien wieder ändern? Also ändern wir mal eine unserer Testdateien…, z.B. indem wir eine zusätzliche Zeile hinzufügen:
$ cat testdatei.txt
Zeile 1
Zeile 2
Diese Zeile geändert, nach dem ersten Commit für diese und andere Datei!
Das ergibt jetzt den folgenden Status:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: testdatei.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git status -s
M testdatei.txt
Also: die Datei im Working Directory weicht vom Zusstand im Index ab! Beachten: hier M in Spalte 2 bei short Status.
Wir aktualisieren die Änderung - fügen also mit git add
die Datei wieder aktuell zum Index.
$ git add testdatei.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: testdatei.txt
$ git status -s
M testdatei.txt
Analyse: die Datei liegt jetzt modified/geändert im Index und ist in dieser Variante für den nächsten Commit vorbereitet.
Jetzt ändern wir die Datei nochmals und schauen uns den Status der Datei in Git an.
$ cat testdatei.txt
Zeile 1
Zeile 2
Diese Zeile geändert, nach dem ersten Commit für diese und andere Datei!
Diese Zeile nach dem add-en der Datei, also dem Hinzufügen zum Index!
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: testdatei.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: testdatei.txt
$ git status -s
MM testdatei.txt
Drei Zustände für eine Datei!
Wenn man so will hat das Git jetzt drei Dateizustände einer
Datei testdatei.txt
:
Lokale Datei im Git-Ordner - aktuellste (lokale) Bearbeitung: 4 Zeilen
Datei im Index (Staging Area) - nach letztem git add: 3 Zeilen
Datei im .git-Repository - nach letztem/ersten git commit: 2 Zeilen (siehe git show)
Wir analysieren das mal der Reihe nach mit ein paar Profi-Aufrufen - Plumbing Git Commands statt Porcelain Git Commands:
Lokale Datei - einfaches
cat
$ cat testdatei.txt Zeile 1 Zeile 2 Diese Zeile geändert, nach dem ersten Commit für diese und andere Datei! Diese Zeile nach dem add-en der Datei, also dem Hinzufügen zum Index!
Datei im Index (Staging Area):
$ git ls-files --stage 100644 c3e447123530f753dbdf7141ed7034609e2fba46 0 testdatei.txt 100644 a33806c56de8e2635b91c78953286fdba2a6ad57 0 testdatei2.txt $ git cat-file -p c3e447123530f753dbdf7141ed7034609e2fba46 Zeile 1 Zeile 2 Diese Zeile geändert, nach dem ersten Commit für diese und andere Datei!
Datei im Git Repository: gerne mit einfachem (oder fein definiertem und dateibezogenen)
git show
:$ git show commit 636908f2b795b68c4c99f978239be5e274bfea05 (HEAD -> master) Author: Joe Brandes <joe.trainer@example.com> Date: Thu Jul 11 14:04:11 2019 +0200 Initial commit; First Commit to .git diff --git a/testdatei.txt b/testdatei.txt new file mode 100644 index 0000000..2fddc57 --- /dev/null +++ b/testdatei.txt @@ -0,0 +1,3 @@ +Zeile 1 +Zeile 2 + diff --git a/testdatei2.txt b/testdatei2.txt new file mode 100644 index 0000000..a33806c --- /dev/null +++ b/testdatei2.txt @@ -0,0 +1 @@ +Text in Datei 2 $ git show HEAD:testdatei.txt Zeile 1 Zeile 2
Und wir können uns mit Git auch die Unterschiede
mittels git diff
präsentieren lassen.
git diff
- Abweichungen zwischen Workspace und Index (Staging Area)git diff --cached
- Abweichungen zwischen Index (Staging Area) und Git Repogit diff HEAD
- Abweichungen zwischen Workspace und Git Repo
Die unterschiedlichen Diff-Beispiele sollten wir uns genauer ansehen.
Varianten git diff¶
Besonders für Trainees, die bereits mit diversen Software- und Versions- Mangements gearbeitet haben ist der Begriff diff bekannt. Allerdings haben wir bei Git durch die unterschiedlichen Orte im Lebenszyklus von Dateien und Ordnern eines Git-Projekts sehr unterschiedliche Abweichungen und Git verwaltet immer das komplette Projekt und nicht einzelne Dateien für diese Vergleiche! Screenshot aus Link training.galaxyproject.org - Version Control with Git

Training galaxyproject.org (/training-material/topics/data-science/images/bash-git/git-staging-area.svg)¶
Es ergeben sich drei mögliche Varianten ein und derselben Datei.
Variante 01: git diff
- Working Directory vs. Index (Staging Area)
Den Unterschied zwischen der Version im Working Directory und
dem Index (Staging Area) erhalten Sie mit git diff
.
$ git diff
diff --git a/testdatei.txt b/testdatei.txt
index c3e4471..701f3e0 100644
--- a/testdatei.txt
+++ b/testdatei.txt
@@ -1,4 +1,5 @@
Zeile 1
Zeile 2
Diese Zeile geändert, nach dem ersten Commit für diese und andere Datei!
+Diese Zeile nach dem add-en der Datei, also dem Hinzufügen zum Index!
Wichtig
Wollen wir also den wirklich letzten Bearbeitungszustand der Datei
in das Repository committen, dann müssen wir hier erst einmal
mit git add testdatei.txt
den Index aktualisieren und danach
mit git commit -m '...'
in das Git Repository einchecken.
Als Hilfe für das Gesamtverständnis: denken Sie immer daran, dass Sie bei Git nicht einzelne Dateien einchecken, sondern immer komplette Zustände (Snapshots).
Variante 02: git diff --staged
- Index (Staging Area) vs. Git Repo
Wenn man stattdessen den Unterschied zwischen dem Index (Staging Area)
und dem .git Repository herausfinden möchte -
also die Unterschiede, die in den nächsten Commit einfließen würden -
dann hilft git diff --staged
.
$ git diff --staged
diff --git a/testdatei.txt b/testdatei.txt
index 2fddc57..c3e4471 100644
--- a/testdatei.txt
+++ b/testdatei.txt
@@ -1,3 +1,4 @@
Zeile 1
Zeile 2
+Diese Zeile geändert, nach dem ersten Commit für diese und andere Datei!
Hinweis
Beim git diff
sind Parameter --staged
und --cached
Synonyme!
Und die letzte Variante folgt zum Schluss:
Variante 03: git diff HEAD ...
- Workspace vs. Git Repo
Befehl: git diff HEAD ...
Nochmals zur Erinnerung: oft der Übersichtlichkeit halber nur eine Datei mit Änderungen! Git interessiert sich aber immer für das gesamte Projekt in den drei Zuständen: Working Directory - Index (Staging Area) - Git Repository!
Für diverse andere Übungen bitte alle Dateien zum Index hinzufügen, damit wieder ein sauberer Git Status herrscht.
Referenzen¶
Git legt alle Infos in Form von Objekten und Referenzen
im .git
-Repository ab.

Git Objekte und Referenzen (siehe gitbu.ch)¶
Hinweis: Darstellungen aus gitbu.ch (siehe auch Literatur).
Objekte |
Beinhaltet / Speichert |
Referenziert andere Objekte? |
Entsprechung |
---|---|---|---|
Blob |
Dateiinhalt |
NEIN |
Dateien |
Tree |
Blobs und (andere) Trees |
JA |
Verzeichniss |
Commit |
Projekt-Zustand |
JA, einen Tree und weitere Commits |
Projekt-Snapshot zum Commit-Zeitpunkt |
Tag |
Tag-Infos |
JA, ein Objekt |
Benennung von Snapshots oder Blobs |
Technik-Info und Erklärung Deduplikation
Selbst, wenn Dateien mehrfach (also in verschiedenen Verzeichnissen) vorkommen, so liegen sie nur einmal in der Objektdatenbank. Es werden einfach mehrfach Trees referenziert.
Duplikate werden nicht nur verhindert, sondern unmöglich gemacht (sog. Content-Adressable File Systems), in denen das Dateisystem die Dateien nur unter ihrem Inhalt kennt. Bei Git kommen SHA-1-Objektsummen zum Einsatz.
Commits erklärt¶
Für eine beispielhafte Folge von Commits (hier 4 Commits: C1 .. C4) versuchen wir folgende graphische Darstellung zu analysieren:

Git Hierarchie (siehe gitbu.ch)¶
Tools zur Analyse: git show ...
oder git ls-tree ...
Hinzu kommen die Tags mit denen man wichtige Snapshots (oder auch einzelne Blobs) referenzieren kann und natürlich die Branches mit denen man komplett neue Zweige für die Entwicklung erstellen und dann später mit anderen Zweigen verschmelzen (mergen) kann.
Diese Techniken kann man in einem Commit-Graph darstellen:

Git Commit Graph (siehe gitbu.ch)¶
Erläuterungen: (Anm.: Bild aus gitbu.ch )
Branches: (grün)
master (hellblau: A - B - C - D - H); mit Bezeichner/Referenz HEAD zu aktuellem Branch
feature (hellrot: E - F)
bugfix (grau: G)
Tags: (Gelb)
v.0.1 (Bezeichner für Commit B)
v.0.2 (Bezeichner für Commit D)
Und - wie immer - auch für die folgenden Techniken immer bedenken:
Wichtig
Commits stellen Schnappschüsse für unser gesamtes Projekt dar.
Also geht es häufig auch um Änderungen in mehreren Dateien und Ordnern. Außerdem haben die Commits einen - oder mehrere - Vorgänger (Parents).
HEAD und Verweise¶
Die Referenz HEAD verweist auf den gerade genutzten (ausgecheckten) Branch - oft hier also einfach main oder master bezeichnet.
$ cat .git/HEAD
ref: refs/heads/master
Eine Übersicht der Referenzen in .git
-Ordner: (hier: Struktur und Objekte)
.git\refs\
├──heads
│ └──master
├──remotes
│ └──origin
│ ├──HEAD
│ └──master
└──tags
Man erkennt (hier) bereits Remote-Referenzen - also Online-Repositories wie auf GitHub und Co.
Über die symbolische Referenz HEAD lassen sich automatisch Commits
ansprechen. Das heißt, wann immer Kommandos wie git log | show
ohne weitere Angabe von Commit-Bezeichnern angewendet werden,
dann wird immer HEAD genutzt.
Also: git show
zeigt letzten (aktuellen) Commit des
(aktuellen) Branch (hier oft noch master).
Für HEAD gibt es die Möglichkeit auf Vorgänger zuzugreifen: HEAD^ oder HEAD~1 bezeichnen hierbei den direkten Vorgänger.
Da es später (siehe Merges) auch mehrere Vorgänger-Commits geben kann erweitert sich diese Syntax:
HEAD^ oder HEAD~1 direkter Vorgänger
HEAD^2 direkter Vorgänger in zweitem Branch usw. HEAD^3, HEAD^4, …
HEAD^^^ oder HEAD~3 dritter Vorgänger
HEAD^2~3 dritter Vorgänger im zweiten Vorgänger-Branch (alternativ: HEAD^2^^^)
Anm.: meist sind die Schreibweisen mit ~
komfortabler für die
meisten Shells!
Tipp
Diese Vorgänger-Techniken lassen sich auch auf SHA-1-Commitbezeichner anwenden!
Branches und Checkouts¶
Immer wieder und bitte niemals vergessen, dass wir im Grunde Referenzen anwenden und nutzen.
In einfachster Form erstellt man mit git branch newbranch
einen neuen Zweig.
Namenskonventionen:
komplett in Kleinbuchstaben; Standardbez.: master, maint, next
Nutzung von Namespaces; z.B. i18n/german, username/hishertesting, pu/feature (proposed updates), ..
Diesen Zweig nutzen wir mit git checkout newbranch
und lassen
uns die Branches mit git branch
anzeigen.
Das Ganze gibt es auch als Einzeiler: git checkout -b newbranch
(erstellen und gleich checkout)
Das entspricht den Aufrufen:
git branch newbranch
&& git checkout newbranch
Test/Übung: git checkout -b testbranch
und gleich mal HEAD checken
$ cat .git/HEAD
ref: refs/heads/testbranch
Übung: wir erstellen mal eine neue Datei testbranch/branchdatei.txt
und ändern eine bestehede Datei.
Danach alles adden und committen…
Wir wechseln also mit git checkout
zwischen Branches
(indem Referenzen umgehängt werden). Der Wechsel wird immer vollzogen,
sofern keine Datenverluste oder Datenüberschreibungen stattfinden!
Es kommt zu Checkout-Meldungen, falls solche Datenverluste drohen!
Szenarien:
Checkout überschreibt Datei im Working Tree, in der sich aktuell Änderungen befinden
Checkout überschreibt eine (noch) ungetrackte (Git unbekannte) Datei
Hier kann (oder besser: könnte) man die Änderungen
mit Schalter -f
forcieren!
Andere git branch
-Kommandos:
mit
-m
einen Branch umbenennen; mittels-M
auch mit überschreibenmit
-d
einen Branch löschen; mittels-D
auch wenn ggf. noch Dinge uncommited oder unveröffentlichtmit
-f
den gewünschten checkout erzwingen; bitte sicher sein, dass Aktion so gewünscht
git checkout
Das Kommando kann auch ältere Versionen von Dateien wiederherstellen:
git checkout sha1summe -- datei.ext
Die --
sind hier als Trenner sinnvoll. Wenn man sich die Dateiinhalte
vorher sichtbar machen möchte, dann hilft: git show sha1summe:datei.ext
Für dieses checkout existiert ein Schalter --patch
(also der interaktive Modus).
Detached Head
Wenn man sich einfach einen kompletten Zustand (sprich: Commit) manuell auscheckt, dann existiert kein Branch und somit auch kein HEAD, #der auf einen Branch referenziert. Das wird durch entsprechende Rückmeldungen von Git zum Ausdruck gebracht.
$ git checkout 67e4ee1
Note: checking out '67e4ee1'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at 67e4ee1 Set theme jekyll-theme-cayman
Hier mal Infos zum HEAD:
$ cat .git/HEAD
67e4ee15514d428d3de4b8d5db190f04b9d79ee9
Anwendungsbeispiel für Detached Heads:
Mit dieser Technik, kann man schauen, wie das Projekt aussah
und natürlich ließe sich jetzt auch mit git checkout -b neuerbranchname
ein eigenständiger neuer Branch erzeugen.
Git nutzen¶
Jetzt haben wir die ersten Techniken rund um Git im Griff und es geht an weitergehende Techniken.

Git benutzen - meinetwegen auch mit Grafiktool (ne!) (Unsplash: yancy-min-842ofHC6MaI-unsplash.jpg)¶
An dieser Stelle mal ein paar Git-Bezeichner für die unterschiedlichen Git-Technik-Umgebungen. Gemeint ist hier die Unterscheidung von
Porcelain-Tools: Standard-Aufrufen für die tägliche Arbeit im Gegensatz zu
Plumbing-Tools: Technik-Aufrufen, die auch mal unter die Haube von Git schauen.
Fangen wir mit ein paar Standard-Tools und Techniken an…
Git Historie - git log¶
Das Standardkommando hier: git log
Tipp
Nutzen eines einfachen Dummy-Git-Repo der ProGit-Book-Writer:
Befehl: git clone https://github.com/schacon/simplegit-progit.git
Mit git log
ohne weitere Parameter werden alle Commits angezeigt,
was bei größeren Projekten dann mit einem Pager geschieht und zum
Beenden q
erfordert.
Für die Anzeige spezieller Commits werden Parameter genutzt.
Patchinfo zu den letzten beiden Commits: git log -p -2
Erkl.: mit Parameter -p
für --patch
und -2
für die letzten 2 Commits)
Für weitere Informationen (Statistik): git log --stat
$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD)
Author: Scott Chacon <schacon@gmail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the verison number
Rakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gmail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test code
lib/simplegit.rb | 5 -----
1 file changed, 5 deletions(-)
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gmail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit
README | 6 ++++++
Rakefile | 23 +++++++++++++++++++++++
lib/simplegit.rb | 25 +++++++++++++++++++++++++
3 files changed, 54 insertions(+)
Und für etwas kompaktere Ausgaben: git log
mit --oneline
-Schalter
$ git log --oneline # Abk. für --pretty=oneline --abbrev-commit
2c0fff5 (HEAD -> master, origin/master, origin/HEAD) .gitignore3 - lets just check in again for clean status und repo
8b90aae .gitignore2 - lets just check in again for clean status und repo
c15b3a6 .gitignore - lets just check in again for clean status und repo
bafdc25 lets just check in again for clean status und repo
636908f Initial commit; First Commit to .git
$ git log --pretty=oneline
2c0fff5041681d70eb909543cd4c1742fcce2f03 (HEAD -> master, origin/master, origin/HEAD) .gitignore3 - lets just check in again for clean status und repo
8b90aae1d35f35ec1782c01a9bc92e3e433f9c98 .gitignore2 - lets just check in again for clean status und repo
c15b3a67b6eaaa983aa40af793a23ab7f830cf05 .gitignore - lets just check in again for clean status und repo
bafdc25f03c5b6ca0a26d4aa4565b095461784c8 lets just check in again for clean status und repo
636908f2b795b68c4c99f978239be5e274bfea05 Initial commit; First Commit to .git
Und dann kann man noch mit dem --format=
Schalter arbeiten:
$ git log --pretty=format:"%h - %an, %ar : %s"
2c0fff5 - Joe Brandes, 4 hours ago : .gitignore3 - lets just check in again for clean status und repo
8b90aae - Joe Brandes, 4 hours ago : .gitignore2 - lets just check in again for clean status und repo
c15b3a6 - Joe Brandes, 4 hours ago : .gitignore - lets just check in again for clean status und repo
bafdc25 - Joe Brandes, 4 hours ago : lets just check in again for clean status und repo
636908f - Joe Brandes, 31 hours ago : Initial commit; First Commit to .git
Hinweis
Tabelle mit Format-Parametern im Pro Git Book (PDF, Page 43, Table 1)
Wenn sich später die Commits verzweigen (siehe Branches),
dann ist in Kombination noch --graph
praktisch.
Weitere Varianten können zeitliche Abfragen erstellen:
git log --since=2.weeks
Eine Abfrage (aus Pro Git Book zum Git-Git-Repo ;-):
$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" --before="2008-11-01" --no-merges -- t/
5610e3b031 - Fix testcase failure when extended attributes are in use
acd3b9eca8 - Enhance hold_lock_file_for_{update,append}() API
f5637549a7 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2aa4 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af845 - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11ea16 - pull: allow "git pull origin $something:$current_branch" into an unborn branch
Da lohnt dann sicherlich mal ein Blick in die Hilfe:
git help log
- Anm.: bisschen Zeit mitbringen ;-)
Logbuch - git reflog¶
Wenn man mal nicht weiß, was man gerade mit seinem Git angestellt hat, dann lassen sich die lokalen Handlungen nachverfolgen:
Aufruf: git reflog
erzeugt z. B.:
$ git reflog show
68269d6 (HEAD -> master) HEAD@{0}: commit: restart of work at seminarstuff - added .gitattributes
59738db (origin/master, origin/HEAD) HEAD@{1}: pull: Fast-forward
0909110 HEAD@{2}: commit: Chapter Books modified
ffc3131 HEAD@{3}: commit: README updated
7abf17b HEAD@{4}: commit: first changes
...
Aha: wir haben also noch nicht ge-push-ed nachdem wir bei der vorletzten Aktion ge-pull-ed hatten.
Mehr zu diesen Remote-Bezeichnern und Techniken später - und dann klären wir auch die HEAD-Bezeichner HEAD@{0} … HEAD@{4}.
git add¶
Die veränderten Dateien im Working Tree übermitteln wir
mittels git add
an den Index.
Im einfachsten Fall könnte man git add -A
(für --all
)
oder auch git add .
(aktuelles Verzeichnis) nutzen.
Dabei verliert man aber beim späterem Nachvollziehen von durchgeführten
Schritten auch ein wenig an Details.
Da man häufig an Ordner-Strukturen arbeitet bietet sich an:
git add Chapter\
(das staged alle Dateien des entsprechenden Ordners)
Wenn man das schrittweise, feingetunte add - commit vernachlässigt hat, dann kann man die entsprechenden Änderungen auch teilweise in den Index schieben und somit dann auch teilweise commiten.
git add –patch - schrittweises/teilweises einchecken von Änderungen
Mit der Option --patch
bzw. -p
gelangt man in den interaktiven
Modus von git add
. Auf diese Weise kann man dann Teile von
Bearbeitungen an Dateien in den Index hinzufügen.
Gründe:
Entwicklungsgeschichte besser erkennbar
Während der Arbeit die kleinteiligen Commits vernachlässigt
Beispiel aus gitbu.ch: Datei hello.pl
# Hello World! in Perl
print "Hello World!\n";
Wird geändert zu:
#!/usr/bin/perl
# Hello World! in Perl
# Author: Valentin Haenel
use strict;
print "Hello World!\n";
Anm.: an dieser Stelle auch mal - zur Erinnerung - die Aufrufe
git diff
vs. git diff --staged
vergleichen bzw. analysieren.
Kommen wir zum Patch-Mode von git add
:
$ git add --patch
diff --git a/hello.pl b/hello.pl
index c6f28d5..1e50e10 100644
--- a/hello.pl
+++ b/hello.pl
@@ -1,2 +1,5 @@
+#!/usr/bin/perl
# Hello World! in Perl
+# Author: Joe B.
+use strict;
print "Hello World!\n";
Stage this hunk [y,n,q,a,d,s,e,?]?s
Wir versuchen den Hunk zu teilen (s für split) und erhalten die folgende Möglichkeit:
Split into 2 hunks.
@@ -1 +1,2 @@
+#!/usr/bin/perl
# Hello World! in Perl
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? y
@@ -1,2 +2,4 @@
# Hello World! in Perl
+# Author: Joe B.
+use strict;
print "Hello World!\n";
Stage this hunk [y,n,q,a,d,K,g,/,e,?]? n
Wir haben also den ersten Teil übernommen und den zweiten Teil nicht für den Index übernommen!
Hier ein Vergleich von git diff
Aufrufen:
$ git diff --staged
diff --git a/hello.pl b/hello.pl
index c6f28d5..d2cc6dc 100644
--- a/hello.pl
+++ b/hello.pl
@@ -1,2 +1,3 @@
+#!/usr/bin/perl
# Hello World! in Perl
print "Hello World!\n";
Und im Working Tree haben wir noch weitere Zeilen:
$ git diff
diff --git a/hello.pl b/hello.pl
index d2cc6dc..1e50e10 100644
--- a/hello.pl
+++ b/hello.pl
@@ -1,3 +1,5 @@
#!/usr/bin/perl
# Hello World! in Perl
+# Author: Joe B.
+use strict;
print "Hello World!\n";
git commit¶
Erinnerung - einfaches Committen mit : git commit -m 'commit-Message'
Hinweis
Die Messages sollten möglichst aussagekräftig sein. Die erste Zeile sollte max. 50 Zeichen lang sein. Man schaue Sie sich doch einmal die Git-Repo Commits an!
Und hier mal ganz extrem:

4 hrs of hacking … 1 commit - Quelle: Chris Lamb, Twitter, Debian Developer¶
Best Practises für das Committen:
Kleinteilig committen: lässt nachträglich die Entstehung von Code besser verstehen. Commits so klein wie möglich und so groß wie nötig.
Niemals Committen ohne Message - also mit leerer Commit-Nachricht
Keine allgemeinen Kurzbezeichner wie Update, Verbesserung oder Fix
Warum wurde eine Änderung committet? (Nicht: Was!)
Anmerkungen zu Fertigkeitsgrad, Verbesserungen, Vorschlägen oder Auswirkungen auf andere Codes
Erste Zeile maximal 50 Zeichen - weiterer Text (Body) dann nach Leerzeile mit max. 72 Zeichen!
Betreff mit Großbuchstaben beginnen - nicht mit Punkt beenden
Befehlsform (Imperativ) anwenden
Link zu Cartoon: ohne Worte

Git Commits (Cartoon)¶
Link zu Blog-Beitrag Chris Beam - How to Write a Git Commit Message (Link zu Blog)
Das wird später auch die Arbeit mit dem Tool git blame
verbessern und effektiver gestalten.
Wenn Sie einen eben gerade gemachten Commit nachbessern wollen -
man hat z.B. Dateien geändert oder hinzugefügt -
oder man möchte die letzte Commit-Message anpassen, dann hilft:
git commit --amend
commit amend
Szenario:
Wir haben Datei(en) geändert und führen eine Commit aus. Dann stellen wir fest, dass wir noch etwas korrigieren und/oder eine Datei vergessen haben.
$ git commit -m 'initial commit - bisschen verfrüht ;-)'
$ git add forgotten_file geaenderte-datei.txt
$ git commit --amend -m 'initial commit'
Also auch bei diesen Commits möglichst mit Option -m '...'
committen,
damit man dem VIm entgeht - falls man das möchte ;-)
Wenn man die letzte Commit-Message unverändert lassen möchte:
git commit --amend --no-edit
Das Umschreiben älterer Commits benötigt andere Techniken und wird an dieser Stelle erst einmal weggelassen.
Zusammenfassung
Es ist besonders wichtig jeweils die Unterschiede in den und - und zwischen den - drei Standard-Ebenen von Git zu erkennen: (zur Erinnerung)
Working Tree
Index (staged)
Lokales Repository (
.git
)
Und wir sollten uns erinnern: Commits sind Schnappschüsse für unser gesamtes Projekt mit Blobs, Trees und Referenzen.
git revert¶
Mit git revert
kann man Commits rückgängig machen:
Dabei werden einfach alle Diffs - also Änderungen - in ihrer Logik invertiert.
Hinzugefügte Zeilen werden also wieder entfernt und umgekehrt gelöschte Zeilen wieder hergestellt. Anm.: hier Begriff Zeilen zur vereinfachten Darstellung.
Die Revert-Commit-Messages enthalten die zurückgenommenen Änderungen und den Hinweis Revert:
* eef31c3 (HEAD -> testbranch) Revert "further new stuff added in testbranch - maybe later reverted?"
* defb51c further new stuff added in testbranch - maybe later reverted?
Es lassen sich auch einzelne Dateien eines Commits Reverten:
git show -R 3329661 -- LICENSE | git apply --index
git commit -m 'Revert change to LICENSE from 3329661'
Analyse: aus einem Commit wird eine einzelne Datei im -R
-(Reverse)-Modus
angezeigt und mittels git apply
weitergeleitet.
Dann findet der Commit statt.
Alternative: manuelles Auschecken einer Datei und ein individuelle add und commit.
Zusammenfassung:
git revert
macht Änderungen lediglich rückgängig - die Commits bleiben
im Git!
git reset¶
Jetzt wollen wir (obere) Commits wieder aus dem Git entfernen / löschen.
Hinweis
Die folgenden Aktionen gehen davon aus, dass die fraglichen Commits
noch nicht auf anderen Repositories veröffentlich worden sind
(siehe git push
)!
Das Löschen von Commits aus der Mitte geschieht mit git rebase
.
Wir arbeiten weiterhin mit Referenzen und können die obersten Commits in einem Branch löschen lassen. Dabei nutzt man gerne die symbolische HEAD Referenz.
Auch für diesen Befehl gibt es den interaktiven Patchmodus mit Option --patch
.

git add | commit | reset (gitbu.ch)¶
Hinweis: Darstellung aus gitbu.ch (siehe auch Literatur).
Parameter mixed
Mit git reset
: Neues/Unterschiede aus dem Repository in den
Index übertragen. Genauer stellt die Grafik und der
Kurzaufruf git reset
den Standardaufruf git reset --mixed HEAD
dar!
Im Grunde wird die Stage (der Index) auf den Zustand des letzten Commits gesetzt!
Parameter soft
Wenn wir den letzten Commit entfernen wollen: git reset --soft HEAD~1
(oder HEAD^
s. o.)
Dabei werden die Dateien im Working Tree nicht angefasst.
Parameter hard
Und git reset --hard
schlägt dann bis den Working Tree durch
und ändert alle Dateinhalte auf die Infos im entsprechenden Projektzustand.
git rm¶
Löschen mit git rm ..
Das Löschen von Dateien/Ordnern ist besonders zu beachten. Wenn man mit einfachem Löschen / Remove eine Datei bearbeitet, so findet dieses ja nur im Working Directory statt.
Stattdessen nutzt man git rm - hierbei wird die Datei zum Löschen im Index hinzugefügt und dadurch beim nächsten Commit aus dem Git Repository entfernt.
Anm.: quasi ein einfaches rm
gefolgt von git add
.
Wenn man eine Datei im Working Directory behalten möchte,
aber aus Git löschen möchte: git rm --cached
Tipp
Das ist z.B. sinnvoll, um nachträglich zu .gitignore
hinzugefügte Objekte lokal zu behalten, aber aus dem Git zu entfernen.
Für die git rm
-Befehle kann man mit Wildcards arbeiten:
git rm log/\*.log # alle .log im Ordner log
git rm \*~ # alle Dateien, die mit ~ enden
Die \
sind (ggf.) wegen der Git-eigenen Dateinamen
Erweiterungsfähigkeit und sequenzieren quasi die Wildcards *
nötig.
git mv¶
Umbenennen mit git mv
Git verfolgt - im Gegensatz zu anderen VCS - keine Dateien
(und Ihre Umbenennungen). Allerdings gibt mit git mv
ein Tool
für eine Abkürzung der sonst umständlichen händischen Umbenennung.
Git speichert also keine Namensänderungen, aber wir werden trotzdem natürlich alle Änderungen nachverfolgen können.
Hier die Vorgehensweise zum Umbenennen in Git - als Erstes mit git mv
$ git mv alter_name neuer_name
# entspricht:
$ mv README.md README
$ git rm README.md
$ git add README
Die Umbenennung findet also auf Umwegen statt: in einem oder in drei Teilschritten.
Hier ein Beispiel für komplette Ordner:
$ git mv Chapters/GitHub/ Chapters/Repositories
dozib@sprectrex360 MINGW64 ~/Documents/git-projekte/rst-gitseminar (master *+ u=)
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: Chapters/GitHub/Index.rst -> Chapters/Repositories/Index.rst
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: Chapters/Repositories/Index.rst
dozib@sprectrex360 MINGW64 ~/Documents/git-projekte/rst-gitseminar (master *+ u=)
$ git status -s
RM Chapters/GitHub/Index.rst -> Chapters/Repositories/Index.rst
Hier taucht jetzt die Kennung R
für Removed auf. und im Workspace
haben wir eine modifizierte Datei.
git stash¶
Mit dieser Technik können wir unsere aktuelle Arbeitsumgebung kurz weglegen und in eine andere Umgebung für Änderungen wechseln. Dann kehren wir zur ursprünglichen Umgebung wieder zurück.
Auch hier wieder ein paar Links zum Einstieg:
Für einen weiteren Einstieg ein Hauptgrund für die Stash Technik von Git: (Hinweis: Übersetzung per perplexity.ai)
Zunächst ist es wichtig zu verstehen, warum das Stashen von Änderungen in Git bedeutsam ist. Nehmen wir für einen Moment an, Git hätte keinen Befehl zum Stashen von Änderungen.
Stellen Sie sich vor, Sie arbeiten an einem Repository mit zwei Branches, A und B. Die Branches A und B haben sich seit einiger Zeit voneinander entfernt und haben unterschiedliche Heads. Während Sie an einigen Dateien in Branch A arbeiten, bittet Sie Ihr Team, einen Fehler in Branch B zu beheben. Sie speichern schnell Ihre Änderungen an A und versuchen, mit
git checkout B
zu Branch B zu wechseln. Git bricht den Vorgang sofort ab und wirft den Fehler: „Your local changes to the following files would be overwritten by checkout … Please commit your changes or stash them before you switch branches.“—Original: „Why is git stash important?“ - opensource.com
Kurzanleitung zum Stashen:
Save changes to branch A.
Run git stash.
Check out branch B.
Fix the bug in branch B.
Commit and (optionally) push to remote.
Check out branch A
Run git stash pop to get your stashed changes back.
Basisaufrufe: (siehe dann ausführliche Anleitungen auf opensource.com - A practical guide to using the git stash command und Atlassian - Git stash)
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
nothing to commit, working tree clean
$ git checkout otherbranch
# Arbeiten erledigen ggf. commiten
$ git checkout -
$ git stash pop
Man sieht, dass der Zustand für das Arbeitsverzeichnis und den Index (Staging Area) weggesichert wurde - der Zauber der Zustände repräsentiert durch Prüfsummen/Hashwerte und Referenzen. Im Grunde ist ein Stash eine besondere Form eine Commits.
Wir können auch mehrfach aus unserer Arbeitsumgebung heraus stashen. Dann sollten wir die Stash namentlich kennzeichnen.
Eine einfache Auflistung der Stash erhalten wir mit git stash list
.
Hier kann man dann die verschiedenen stash@{..} Referenzen und
Bezeichner (WIP ?) kombiniert mit der Info zum Branch aus dem die Stash
erstellt worden sind.
Die Standardbezeichnung lautet WIP für „Work in Progress“, was bei
mehreren Stash unübersichtlich wird. Für individuelle Message kann man
git stash save "Info for Stash"
nutzen.
Und natürlich sollte man nach der Nutzung von solchen Git-Zwischenablagen
auch aufräumen: git stash drop stash@{1}
oder auch git stash clear
.
git worktree¶
Wir haben wieder den Wunsch den Arbeits-Branch zu wechseln (s. a. Stash). Wir wollen aber unseren aktuellen Arbeiten weder comitten noch stashen.

Git Worktree - Checkout Multiple Git Branches at Once (YouTube GitKraken)¶
Am Besten wäre, wenn wir beliebig zwischen den Branches unseres Git Repo wechseln könnten - als wären diese einfach Verzeichnissse! Und genau das leistet die Technik Git Worktrees.
GitKraken - GitLens YouTube Video - Git Worktree | Checkout Multiple Git Branches at Once
The Primagen - Git Worktree - Gits Best And Most Unknown Feature - YouTube
Kurzbeschreibung für Git Worktree
Wir haben ein Projekt in Git-Ordner /home/joeb/testing-01
und arbeiten
im Branch feature an neuen Techniken. Durch diese Arbeiten ist
der Git-Status wieder nicht clean und wir können nicht für notwendige
Reparaturen in Branch main wechseln - und wir wollen nicht committen und
nicht stashen!
Man kann jetzt einfach für den Branch main einen Worktree erstellen und nutzen.
$ git worktree add ../testing-01-wt/main
$ cd ../testing-01-wt/main
# Branch main nutzen / bearbeiten / commiten / pushen ...
$ cd ../../testing-01
$ git worktree remove ../testing-01-wt/main
Genau wie die Stash, sollte man also auch hier nach den Nutzungen wieder die Arbeitsumgebung säubern.
Hinweis: mit git worktree list
erhält man stets eine Übersicht über die
genuzten Directories und und zugeordneten Branches.
Bare Repo¶
Ein Bare Git Repo enthält keine Workspace Daten sondern nur die rohen Git Repo Infos. Ein solches Bare Repo wird häufig als Remote Repository zum Abgleich zwischen verschiedenen Bearbeitern genutzt.
Anwendungsbeispiele:
How i use Git Worktrees in my Developer Workflow (YT)
Zugehöriger Artikel des YouTuber Nicknise - How I use git worktrees
Ein leeres Git-Repository kann man schnell erstellen:
$ pwd
/c/Users/username/Documents/git-repositories/testing
$ git init --bare
Initialized empty Git repository in C:/Users/username/Documents/git-repositories/testing/
$ ll
total 7
-rw-r--r-- 1 dozib 197610 104 Aug 8 10:29 config
-rw-r--r-- 1 dozib 197610 73 Aug 8 10:29 description
-rw-r--r-- 1 dozib 197610 23 Aug 8 10:29 HEAD
drwxr-xr-x 1 dozib 197610 0 Aug 8 10:29 hooks/
drwxr-xr-x 1 dozib 197610 0 Aug 8 10:29 info/
drwxr-xr-x 1 dozib 197610 0 Aug 8 10:29 objects/
drwxr-xr-x 1 dozib 197610 0 Aug 8 10:29 refs/
Wir haben uns also ein bares / leeres Git-Repository
mit git init --bare
in einem vorbereiteten Repo-Ordner erstellt!
Und natürlich darf dieser Ordner auch auf externen
Speichermedien oder auf einem NAS sein.
Für klassische Linux-Mounts und manuelle Sicherung, ohne Extra-Konfigurationen:
$ git init --bare /mnt/usb/repo-backup/
$ git push --all /mnt/usb/repo-backup/
Und so kann das bei der Windows Git Bash aussehen:
$ git push --all /c/Users/username/Documents/git-repositories/testing/
Enumerating objects: 91, done.
Counting objects: 100% (91/91), done.
Delta compression using up to 8 threads
Compressing objects: 100% (73/73), done.
Writing objects: 100% (91/91), 9.89 KiB | 206.00 KiB/s, done.
Total 91 (delta 28), reused 0 (delta 0)
To C:/Users/username/Documents/git-repositories/testing/
* [new branch] master -> master
* [new branch] testbranch -> testbranch
Und das Ganze lässt sich wieder an beliebigen Ordner per clone wiederherstellen. Bitte beachten: beim Klonen entsteht wieder ein neuer Ordner:
$ git clone /c/Users/username/Documents/git-repositories/testing/
Git LFS¶
Mit Git LFS - Large File System erhalten wir eine Lösung zu einem vermeintlichen Horror-Szenario für ein Git-Repo: große binäre Dateien.
Sammlung von Screenshots / Hintergrundbildern
Große Anzahl von 3D-Modellen, Audio oder Video Dateien
Der folgende Screenshot zeigt die 2-fache Überarbeitung einer großen Bilddatei mit Ursprungsgröße von 50 MiB. Nach den zwei Überarbeitungen sid die Git-relevanten Infos auf 150 MiB angewachsen! Das Bild ist jetzt halt in 3 Snapshots (Commits) unseres Projekts!

YouTube: Atlassion - Tim Pettersen - What is Git LFS?¶
Wir starten aber wieder mit einer kleinen Linkliste zu Git LFS - Git Large File Storage.
Für die weiteren Erklärungen zitiere ich einen der Kollegen aus der Linkliste zum Thema Git LFS:
Ich möchte gar nicht lange um den heißen Brei herumreden: Git ist eine Versionsverwaltung, die hervorragend mit Textdateien bzw. Source Code zurechtkommt, aber nicht mit Binärdateien (Bilder, Musik, Videos, etc.).
Jetzt ist es aber so, dass man gelegentlich doch gleichzeitig Code und Binärdateien in einem Repository braucht.
Bis ca. 1 GB Daten klappt das auch noch recht gut, aber darüber wird’s wirklich unangenehm. Leider sind meine Repos, bei denen ich Binärdateien mit drin habe, mittlerweile 2-50 GB groß, und um’s kurz zu sagen: Das macht einfach keinen Spaß mehr.
—Elia „KopfKrieg“, 26. Apr. 2022, kopfkrieg.dev/2022/04/26/git-lfs/
Die Git Extension Git LFS löst dieses Problem auf. Welches Problem war das nochmal? Bei Git handelt es sich um ein Distributed Version Management. Beim Klonen des Repos erhält ein Nutzer alle Versionen aller Dateien nach Abschluss des Clone-Vorgang. Das ist bei großen binären Dateien das Problem!
Git LFS erweitert die Fähigkeiten von Git um einen LFS store, der die Dateien außerhalb der Git-Arbeitsumgebung speichert. In den Snapshots/Commits verweisen nur noch Links auf die entsprechenden Dateiversionen. Bei einem Pull wird nur die letzte Version heruntergeladen.

YouTube: git (lfs) pull - Tim Pettersen - What is Git LFS?¶
Und selbstverständlich erhält man auch auf den anderen Commits die entsprechenden Bildversionen bereitgestellt.
Wenn man weiß, dass man es mit einem LFS unterstüzten Repo zu tun hat,
dann kann man diese Info beim Klonen hinzufügen: git lfs clone
.
Dadurch wartet man auf die Beendiugung des Checkouts für den fraglichen
Commit und erst danach werden die fraglichen LFS-Dateien in einem Zug und
mit parallelisierten Downloads im LFS-Cache bereitgestellt.
Aliase¶
Beim Arbeiten in der Konsole sollte man sich mit effizienten Aliasen unterstützen. Hierfür können wir uns an verschiedenen Techniken bedienen.
Git Aliase mit git alias ...
Unsere Git Konsolentools enthalten eigene Aliase, die man in den Git Konfiguration ablegen kann.
Anleitungsbeispiele aus der git-scm.com Dokumentation :
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
# Anwendungsbeispiel: aus git checkout wird
$ git co
Man sieht also, dass man den Technikbegriff Git Alias wörtlich nimmt:
der Alias wird quasi zum neuen Subbefehl für git
.
Aliase für genutzte Shells
Im Normalfall findet Git in einer Linux-Shell - Bash oder auch Zsh -
statt. Also definieren wir uns einfach beliebig Sammlungen von alias
Anweisungen.
Ablage für Aliase:
in den passenden Konfigurationsdateien der jeweiligen Shells (
~/.bashrc
bzw.~/.zshrc
)eigenständige Scriptdatei und in Konfigurationen sourcen
oder falls verfügbar Profildateien für alle Shells nutzen:
~/.profile
Anregungen für Aliase: Git Plugin Oh-My-Zsh
Merges¶
Man kann mit Branches (dt.: Zweigen) verschiedene Entwicklungen (allgemein: Inhalte) getrennt bauen.
Das Basistool zum zummenbauen ist git merge ...

Zwei Branches mergen - Darstellung aus gitbu.ch (siehe auch Literatur)¶
Solche Zweige sollen wieder dem allgemeinen master verinnerlicht werden. Das heißt wir wollen Branches zusammenführen: mergen - eigentlich also ein Merge-Commit.
Spätere (mögliche) Merge-Konflikte kann man über sauberes Planen und Nutzen von Branches im Vorfeld vermeiden - über solche Merge-Konflikte später mehr.
Und überhaupt ist die dezentrale Git-Verwaltung in dieser Hinsicht (technisch) besser aufgestellt als zentrale Systeme.
Auch an dieser Stelle sei erinnert an:
kleine (gemeint: kleinteilige) Commits erstellen
Branches zu Topics immer auf neuesten Releases (master) aufbauen lassen
Merge-Richtung: die Topic Branches in Branches sammeln und dann in den master
in Entwickler-Gruppen/Teams: gute Kommunikation pflegen
alle automatisch generierbaren Dateien aus dem Git-Projekt exkludieren
Für letzte Anmerkung ist diese Ausarbeitung ein Beispiel: der _build
Ordner für die per rST/Sphinx gebauten „HTML/SingleHTML/LatexPDF“
Dokumente gehört nicht zu Git! Wenn man auf unterschiedlichen Rechnern
immer mal wieder Versionen bauen und einchecken würden, dann
gäbe es sicherlich Probleme (Konflikte) einen gemeinsamen Nenner zu finden.
Merge-Commit¶
In dem vorliegenden Beispiel gibt es also einen Entwicklungszweig topic, der quasi parallel zum Hauptzweig master entwickelt wird. Die genauen Vorgehensweisen von Git beim mergen kann man der weiterführenden Literatur entnehmen. Hier in Kürze:
Eine Datei aus den Commits besitzen verschiedene Blobs - weichen also in den beiden Zweigen ab.
Ist Blob mit der Merge-Basis gleich, dann muss nur die Änderung im zu verschmelzenden Commit eingearbeitet werden.
Wenn sich beide Blobs einer Datei von der Merge-Basis unterscheiden, versucht Git beide Änderungen in der Datei einzuarbeiten (techn.: 3-Wege-Merge-Algorithmus).
Für die strategische Umsetzung kennt Git folgende Vorgehensweisen:
resolve
recursive (Standard)
octopus
ours
subtree
Die Standard-Option recursive
(zwei Branches) kann
mit -X ...
noch Optionen bekommen:
ours
theirs
ignore-space-change, ignore-all-space, ignore-space-at-eol
subtree=Verzeichnis
Link zur Dokumentation: https://git-scm.com/docs/git-merge
Fast-Forward-Merges¶
Ein Fast-Forward-Commit ist eine häufig bei Einzelprojekten entstehende Merge-Logistik.
Wenn man z. B. einfach von unterschiedlichen Projektumgebungen und alleine auf einem zentralen, öffentlichem Repository arbeitet, dann setzt man mit wechselnden Aktualisierungen (push) und Herunterladen (pull) von Git Repositories immer wieder mit den lokalen Entwicklungszweigen oben fort.
Hierzu eine passende Grafik: (wieder gitbu.ch)

Zwei Branches vor FF-Merge¶
Wenn man jetzt git merge
durchführt erhält man:

Zwei Branches nach FF-Merge¶
Im Grunde kein Problem, denn alle notwendigen Dateien und Ordner wurden (sicherlich) sauber verschmolzen.
Aber: der verschmolzene master wird einfach nur gerade gezogen
und somit ist nachträglich im git log
der frühere Zweig nicht mehr erkennbar.
Daher kennt man folgende Parameter, um das gewünschte Merge-Verhalten zu steuern:
Parameter
--no-ff
(kein Fast-forward)Parameter
--ff-only
(Fast-Forward nutzen)
Hier das Git-Logging in den zwei möglichen Varianten:

Merging mit und ohne Fast-Forward¶
Für das Standardverhalten beim Mergen kann man Git Konfigurationen nutzen.
Git Dokumentation zur Configuration Git Merge: https://git-scm.com/docs/git-merge#_configuration
Merge-Konflikte¶
Eine sehr praxisrelevantes Beispiel gibt es in Kapitel 3.4 Merge-Konflikte lösen aus dem gitbu.ch.
Wir halten unser Beispiel ein wenig kleiner: Ruslan Osipov - Autor von Mastering Vim mit Blogeintrag .
Da geht es dann auch gleich um die clevere Nutzung von Vim bzw. vimdiff als Mergetool.
Wir erstellen uns in einem master eine Datei animals.txt
mit Inhalt:
Katze
Hund
Octopus
Marienkäfer
Datei im master adden und committen:
git add animals.txt
git commit -m "Initial commit"
Neuen Branch octodog anlegen und den Inhalt bei Text Octupus ändern, adden, committen:
git branch octodog
git checkout octodog
vi animals.txt # let's change Octopus to Octodog
git add animals.txt
git commit -m "Replace Octopus with an Octodog"
Wieder in den Branch master zurück und auch hier (abweichende) Änderung am Octupus, adden, committen:
git checkout master
vi animals.txt # let's change Octopus to Octoman
git add animals.txt
git commit -m "Replace Octopus with an Octoman"
Und dann versuchen wir mal einen git merge octodog
,
was zu einem Konflikt führt:
$ git merge octodog
Auto-merging animals.txt
CONFLICT (content): Merge conflict in animals.txt
Automatic merge failed; fix conflicts and then commit the result.
Bevor man jetzt die Datei added und commited kann man sich noch per Git den Merge erklären lassen:
git log --merge
bzw. mit Patches git log merge -p
Bei mehreren Dateien gezielt für eine Datei mit
git log --merge -p -- dateiname.ext
Mit git show :<n>:animals.txt
kann man sich auch (n = 1,2,3)
die drei Versionen zeigen lassen.
Tipp
Mit git merge --abort
kann man jederzeit einen Merge-Versuch
abbrechen und von Vorne anfangen. Und einen funktionstüchtigen
Merge kann man mit git reset --hard HEAD~1
zurücksetzen.
Mergetool vimdiff
Wenn man Rückfragen nach dem Tool vermeiden möchte:
git config --global merge.tool vimdiff
Und jetzt rufen wir endlich git mergetool
auf und haben es
bei Standardkonfiguration mit dem vimdiff
Tool des VI
zu tun.

Mergetool vimdiff¶
Man erkennt im oberen Bereich die drei Versionen der Datei animals.txt
:
LOCAL (LO)
BASE (BA)
REMOTE (RE)
Die Kürzel können für die vimdiff
-Kommandos genutzt werden. Wir können uns
also über die Konflikt-Zone positionieren und mit ESC
, :diffget LO
übernehmen wir den Eintrag Octoman.
Alles (a) speichern (w) und schließen (q) mit :wqa
.
Jetzt zum Übernehmen noch ein git commit
und fertig!
Anm.: hier ohne -m
für Standard-Message Merge branch ...
Hinweis
Das Verhalten und die Konfiguration eines Mergetools kann ausgiebig
konfiguriert werden. Insbesondere wird mit
git config --global mergetool.keepbackup false
verhindert,
dass vimdiff lokale Backups nach Änderungen pflegt (.orig-Dateien).
Merge-Specials¶
Merge vs. Rebase
Beim Zusammenführen von unterschiedlichen Zuständen desselben Branches gibt es zwei unterschiedliche Philosophien, deren genauere Betrachtung wichtig ist.
Siehe (z.B.): Git team workflow: merge or rebase? - Oct 25, 2018 by LJ MIRANDA

Merge vs. Rebase¶
Quelle: Git Merge vs Git Rebase by Soumyajit Dutta
Spezialthema: Rerere
Bedeutet Reuse Recorded Resolution und heißt, dass man Konfliktlösungen in diesem Modus speichern lassen und somit bei gleichen Konflikten dann auch automatisiert anwenden lassen kann.
Für diese Technik braucht man: git config --global rerere.enabled true
Diese Technik wird häufig bei langen (zum master parellelen) Topic-Branches benutzt, um nicht erst am Ende feststellen zu können, wie gut man mergen kann.
Auch beim sogenannten Rebase mit Git (siehe Commits verschieben / nachbearbeiten) kann diese Technik eingesetzt werden.
Spezialthema: Cherry-Pick
Hier sucht man sich zu mergen nur gezielt den oder die gewünschten Commits aus einem anderen Branch heraus.
Beispielhafte Aufrufe:
$ git cherry-pick d0c915d # 1 Commit
$ git cherry-pick topic~5 topic~1 # 2 Commits
$ git cherry-pick topic~5..topic~1 # Commits einer Range
Gefahr
Nach Cherry-Picks können komplette Merges später Konflikte hervorrufen!
Cherry-Picking¶
Merges fügen normalerweise alle Änderungen von Branches zusammen. Das ist allerdings manchmal nicht gewünscht. Manchmal möchte man - oder muss man - sich auch mal die Rosinen rauspicken.
Für den Einstieg erst mal wieder ein paar Links:
Wir stellen uns folgendes Szenario vor:
Unsere Software liegt (natürlich) im Branch master vor. Wir arbeiten gerade an einem neuen Feature und arbeiten entsprechende im Branch feature.
Kollegen stellen einen Fehler im Branch master fest - dieser muss behoben werden. Also wechseln wir in den Branch und beheben den Fehler.
git checkout master
...
git commit -a -m 'CORRECT bugfix for problem xyz'
[master ac55a30] CORRECT bugfix for problem xyz
Der Fehler wurde somit durch diesen Commit behoben und sehr wahrscheinlich wurden im Branch master davor auch noch anderen Änderungen commited.
Beim Mergen in unseren Arbeits-Branch feature würden wir alle diese Commits zusammfügen. Wir wollen aber womöglich nur die eine Fehlerbehebung unseres Commits ac55a30 in unseren Branch feature übernehmen.
Kein Problem - wir wechseln einfach wieder in unseren Arbeits-Branch und picken uns nur die eine Änderung aus dem master Branch heraus.
git checkout feature
git cherry-pick ac55a30
Und natürlich kann es auch bei dieser Sonderform eine Merges zu Merge-Konflikten kommen, die man auflösen muss.
Und selbstverständlich kann man das Szenario auch umdrehen:
Wir wollen im Branch master nur eine bereits entwickelte Änderung - einen bestimmten Commit - eines Entwicklungszweiges nutzen.
Teamwork¶
Git ist ein verteiltes - dezentrales - Verwaltungssystem. Das bedeutet, dass alle Entwickler lokal am gemeinsamen Projekt arbeiten können ohne das hierfür ein Zugang zu einem zentralen Projektserver nötig ist.

Git - Verteiltes System¶
Quelle Wikipedia: Urheber Paul Vincent
Aber natürlich muss bei Entwicklungsteams der Informationsfluss gesteuert werden. Hierzu wird einfach ein (oft öffentlich) erreichbarer Git-Service als Haupt-Repository oder auch Zentrales Repository definiert.

Git - Haupt-Repository¶
Hinweis: Darstellung aus gitbu.ch (siehe auch Literatur).
Ein paar Begriffe und Aufrufe für die Verwaltung dieser Techniken:
Remote Repository oder einfach kurz remote - Öffentliches (oder genauer: nicht das lokale mit Working Tree kombinierte) Repository
git remote
- Allgemeine Konfiguration von Remotes: hinzufügen, entfernen, umbenennen usw.git clone
- Komplette Kopie herunterladen.git pull
undgit fetch
- Commits und Referenzen aus einem Remote herunterladen.git push
- Commits und Referenzen in ein Remote hochladen
git clone¶
Für das Klonen benötigen wir ein bestehendes Öffentliches Repository. Durch das Klonen werden gleich die zugehörigen Konfigurationen erstellt. Diese Konfigurationen muss man bei neuen lokalen Git-Projekten später manuell nachholen oder nach gewünschter Umsetzung anpassen.
Git unterstützt für das Klonen unterschiedliche Protokolle:
git - ohne Authentifizierung (obsolet)
ssh - verschlüsselt und inkl. Auth.
http(s) - verschlüsselt mit https z.B. für GitHub, …
Einfaches Ausschecken / Klonen eines Git-Repo: (hier mit Git-Protokoll)
### git clone git://github.com/esc/git-cheatsheet-de.git OrdnerNachWunsch
$ git clone git://github.com/esc/git-cheatsheet-de.git
Cloning into 'git-cheatsheet-de'...
remote: Enumerating objects: 77, done.
remote: Total 77 (delta 0), reused 0 (delta 0), pack-reused 77
Receiving objects: 100% (77/77), 132.44 KiB | 832.00 KiB/s, done.
Resolving deltas: 100% (45/45), done.
Beim Klonen kann man den zu erstellenden Git-Projekt-Ordner bestimmen
oder mit Option -o
den Remote-Namen (abweichend von origin) bestimmen.
Infos zum Remote: (Anm.: weitere Aufrufe wie immer
mit git remote TAB TAB
bzw git remote --TAB TAB
$ git remote -v
origin git://github.com/esc/git-cheatsheet-de.git (fetch)
origin git://github.com/esc/git-cheatsheet-de.git (push)
Die Infos sind auch in der .git/config
zu finden:
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = git://github.com/esc/git-cheatsheet-de.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
Die Bearbeitung dieser Konfiguration kann man mit git config -e
aufrufen - oder natürlich die .git/config
direkt bearbeiten.
Einzelbefehl zum Anpassen der Remote-URLs: git remote set-url ...
Die Verwaltung der Infos und Zustände für lokal / remote müssen wir mit Git managen können.
Remote-Tracking-Branches¶
Immer wieder erinnern: Branches (egal, ob lokal oder remote) sind immer Referenzen.
Man braucht diese jetzt sauber an den jeweilgen Projekt-Umgebungen. Hierfür werden jeweils die Branches-Bezeichner völlig gleich umgesetzt. In der lokalen Umgebung bekommen beim Abgleichen der Infos die Branches entsprechende besondere Bezeichner zum Einsatz.

Git - Klonen¶
Hinweis: Darstellung aus gitbu.ch (siehe auch Literatur).
Die Branches lassen sich getrennt oder gemeinsam anzeigen:
git branch
bzw.git branch -v
- Lokale Branchesgit branch -r
- Remote Branchesgit branch -a
- Alle Branches
Hier das Beispiel für das Git-Repo:
$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/maint
remotes/origin/master
remotes/origin/next
remotes/origin/pu
remotes/origin/todo
Jetzt wollen wir uns die Infos aus den Remote-Branches lokal bereitstellen. Also müssen wir diese holen (engl. fetch).
git fetch¶
Mit diesem Basis-Download-Kommando werden einfach die zum Lokal-Branch abweichenden (neuen) Commits heruntergeladen und mit den Remote-Tracking-Branches referenziert.

Git - Fetch (gitbu.ch)¶
Hinweis: Darstellung aus gitbu.ch (siehe auch Literatur).
Das Basiskommando git fetch
arbeitet mit den Spezifikationen,
die in der Git-Config mittels der Reference Specifications (RefSpec)
hinterlegt sind.
Also schauen uns wir uns wieder .git/config
an:
$ cat .git/config
...
[remote "origin"]
url = git://github.com/esc/git-cheatsheet-de.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
Die RefSpec werden automatisch mittels git clone
oder git remote add
aktualisiert.
Die komplette Syntax wäre git fetch origin master
-
hole (fetch) aus origin (siehe RefSpec) den Branch master
Um die Neuerungen mit lokalen Zweigen zu verschmelzen benötigen wir noch ein git merge
.
Wenn man andere Branches, als den (meist) per RefSpec verdrahteten master fetchen will,
dann führt man ein git checkout
durch:
$ git checkout -b next origin/next # komplette Syntax
$ git checkout next # ausreichende Info, falls lokal kein Branch next
Immer auch hierbei beachten: alle Arbeiten finden lokal statt, auch wenn wir hier jetzt durch Checkouts mit Remote-Tracking-Branches arbeiten.
Nur durch git push
werden Änderungen (online) veröffentlicht!
git pull¶
Der Befehl vereint die Befehle git fetch
und
git merge
(bzw. git rebase
).
Komplettes Kommando: git pull origin master
(Erkl.: wie bei git fetch)
Das Git-Buch versucht diesen Prozess mit der folgenden Skizze deutlich zu machen. Aber…
Hinweis
In dieser Situation gibt es neue Commits auf Remote- und Lokal-Branch!
Der Standard-Pull ist ein klassischer Merge und führt zu:

Git - Pull (Merge)¶
Hinweis: Darstellung aus gitbu.ch (siehe auch Literatur).
Hinweis
Wenn man alleine an Projekten arbeitet, dann wird dieser Vorgang erheblich vereinfacht, da es bei einem Pull aus einem Remote entweder keine Neuerungen oder einfach nur die (von anderen Entwicklungsrechnern) zu aktualisierenden Commits vorzuspulen gilt!
In diesem Beispiel werden die beiden Referenzen origin/master (Remote-Tracking-Branch) und
master (lokaler Branch) nach dem nächsten Veröffentlichen (git push
) auf denselben
(letzten) Commit M zeigen.
Bei diesem einfach git pull wird also die Abzweigung C weiter mit gepflegt. Wenn man den Branch sauber in einer Linie von Commits haben möchte, dann könnte man den Pull auch mit einem Rebase (also: Neubau) beauftragen.
Tipp
Vor dem vollständigen Verständnis von Rebase-Techniken und -Problemen und deren Lösungen sollte von diesen git pulls abgesehen werden!
Hier ein Rebase, basierend auf gleicher Ausgangsbasis wie oben:

Git - Pull (Rebase)¶
Hinweis: Darstellung aus gitbu.ch (siehe auch Literatur).
Hierbei ist zu beachten, dass der originale Commit D jetzt als neuer Commit D‘ im Branch zu finden ist! Allerdings handelt es sich ja um unseren eigenen lokalen Commit und dieser war ja noch nicht veröffentlicht.
Solche Rebase-Techniken sind fortgeschrittene Techniken, die auch zum Verschieben von Commits genutzt werden. Die Gedanken (s.o.) zum nachträglichen Anpassen von bereits veröffentlichten Commits sind stets wichtig und zu verinnerlichen.
Hinweis
Die argumentlosen Aufrufe von git fetch
, git pull
und auch git push
sind vorbehaltlich der Definition von Upstream-Branches (siehe wieder Config). Für
den Fall, dass diese Upstream-Branches nicht definiert sind, kommt es zu Fehlern.
git push¶
Wir wollen lokale Änderungen in einen Remote-Branch übernehmen:
git push origin master:master
oder einfach kurz git push
(siehe Upstream-Definitionen)
Das führt für die obigen Beispiele zu folgender Situation:

Git - Push¶
Hinweis: Darstellung aus gitbu.ch (siehe auch Literatur).
Gefahr
Beispiele für Vorgehensweisen, die Probleme erzeugen kann: Nachträgliches Verändern von Commits per Rebase oder commit –amend
Für ein Erzwingen der Änderungen kann man den Push forcieren:
$ git push origin --force master
$ git push origin +master
Für das Löschen von Referenzen (z.B. Branches) im Remote-Git:
git push origin --delete refname
Anm. alte Syntax: git push origin :refname
Das Verhalten von git push
lässt sich über verschiedene
Konfigurationen anpassen: git config push.TAB TAB
Remotes¶
Wir können die Git Remotes einfach untersuchen:
git remote show
(zeigt Remote Bezeichner) gefolgt
von git remote show origin
$ git remote show origin
* remote origin
Fetch URL: https://github.com/.../testing.git
Push URL: https://github.com/.../testing.git
HEAD branch: master
Remote branches:
B new (next fetch will store in remotes/origin)
master tracked
octodog new (next fetch will store in remotes/origin)
testbranch tracked
Local branch configured for 'git pull':
master merges with remote master
Local refs configured for 'git push':
master pushes to master (local out of date)
testbranch pushes to testbranch (local out of date)
Diese Analyse zeigt
Origin URLs
zwei neue Branches: B und octodog
Local Branches master und testbranch sind out of date und bereits tracked
Natürlich benötigen wir für solchen Anfragen die ausreichenden Berechtigungen.
Zusatzinfos¶
Forks und Pull-Requests
Das klassische GitHub Portal hat hiermit die Möglichkeit zum Vorschlagen von Code-Updates inteegriert.
Ein Fork - per einfachem Klick in der GitHub Weboberfläche - erstellt ein eigenes Repo mit dem Original-Repo. Mit diesem geforkten Repo kann man dann arbeiten (lokal) und in den Fork pushen.
Nun kann man für die geänderte Datei einen Pull-Request erstellen. Das führt einen auf die Original-Repo Seite, wo man in entsprechenden Formularen die gemachten Änderungen dargestellt bekommt und diese mit aussagekräftigen Bemerkungen komplettiert. Das wird dann an das Original-Repo übermittelt und steht als Pull-Request den Besitzern des Repos zur Verfügung.
Meine 5 Cent zur Bezeichnung Pull-Request - call it Merge-Request
Ich finde, dass der Bezeichner eigentlich Merge-Request heißen sollte. Die auszulösende gewünschte Handlung ist ja kein Pullen, sondern im Falle von Übernahme des P-R ein mergen.
Workflows
Das stellt ein Riesenthema dar und sollte in Teams gesondert geklärt und optimiert werden.
Verweis: Kapitel 6. Workflows aus gitbu.ch (siehe auch Literatur).
Hier kommen häufig auch Sonderthemen wie Submodule und Subtrees zum Tragen.
Patches per Mail
Ein ganz besonderer Workflow, der in vielen Kernel-Entwicklungen immer noch genutzt wird.
Anm.: oft werden hier klassische normale Mailer wie Outlook, Thunderbird vermieden!
Repositories¶
Wir arbeiten bisher immer mit Ordner .git
und schauen also immer auf
einen Projektordner, der das Arbeitsverzeichnis und
das Git-Repository gemeinsam enthält!

Git Repo Anbieter GitLab.com (Unsplash: pankaj-patel-ZV_64LdGoao-unsplash.jpg)¶
Prinzipiell lassen sich Git-Projekte natürlich auch selbst hosten - und hier gerne auch mit dem ganzen Webkomfort und Administrationstools.
Und die lokale Bereitstellung (onPremise) stellt sowohl im Enterprise- als auch im Privaten Bereich keine Hürde mehr dar.
Die meisten öffentlichen Plattformen bieten neben dem reinen Git-en diverse modernen Techniken im Rahmen von DevOps-Techniken, Werkzeugkästen und Tool-Chains (siehe CI/CD).
Eine erste Übersicht zu öffentlichen Repository-Dienstleistern
Klassiker github.com (Microsoft)
GitLab (gitlab.com )
Gitea (gitea.com)
Codeberg (codeberg.org)
Bitbucket (Fa. Atlassian - Bitbucket)
… diverse andere Plattformen
Eine Auswahl des richtigen Git-Repo-Anbieters kann sich nach vielen individuellen Kriterien orientieren: Container-Techniken, Support, Zusatzwerkzeuge, Kosten, Privatsphäre/Dateinschutz oder auch Ausrichtung Enterprise vs. Community.
GitHub¶
Das Beispiel GitHub kann z.B. mit anderen Werkzeug-Plattformen wie Docker-Hub zusammenarbeiten. So kann man Dockerfiles sauber mit Git verwalten und den Docker-Hub automatisch neue Docker-Images bauen lassen.

GitHub.com - Account erstellen¶
Ein Account auf github.com ist schnell erstellt. Seit kurzem (ca. Anfang 2019) gibt es auch hier unbegrenzt Private Repositories!
Hier die Vorschläge des GitHub-Portals für das weitere Verfahren bei einem neuen Repository (siehe auch --bare
).
Neues Git-Projekt per Kommandozeile erstellen und dann pushen:
echo "# seminar" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/username/seminar.git
git push -u origin master
Ein Git-Projekt konfigurieren für GitHub.com und dann wieder pushen:
git remote add origin https://github.com/username/seminar.git
git push -u origin master
In einem existierenden Projekt wird sehr wahrscheinlich die Remote-Bezeichnung origin schon definiert
sein! Siehe git remote -v
bzw. die Konfigurationen mit git config --list
auflisten lassen.
Hinweis
Wenn Sie auf einem Windows Git System mit dem ersten Remote-Repo konnektieren, dann wird die Connection über Windows-Anmeldeinformationen (siehe Systemsteuerung) verwaltet: EIN (!) Personal Token!
Für weitere Konnektionen geben Sie die Zugangstechnik über Git/SSH an und nutzen SSH-Keys.
Wenn (bei Windows) solche Personal Tokens hinterlegt werden, dann sollte man auch entsprechende Mails beachten: (Link: GitHub Tokens )
Hey ghusername!
A personal access token (git: https://github.com/ on MASCHINENNAME at 08-Aug-2019 13:06) with gist and repo scopes was recently added to your account. Visit https://github.com/settings/tokens for more information.
To see this and other security events for your account, visit https://github.com/settings/security
Also besser:
git remote add ghbezeichner git@github.com:ghusername/seminar.git
git push -u ghbezeichner master
Anleitungen für das Hinterlegen von SSH-Public-Keys auf github.com gibt es diverse. Hier die Anleitung direkt von GitHub: Anleitung auf github.com-Portal
Für die Nutzung von GitHub.com hat die Portalgemeinschaft eigene Anleitungen und Tutorials hinterlegt: GitHub Tutorials und Co
GitLab on Premise¶
Für die Nutzung von GitLab in der eigenen Umgebungen gibt es in der GitLab Documentation - Installation methods verschiedenste Umsetzungen.

Install GitLab in a Docker container - Docs GitLab¶
Eine Übersicht zu den möglichen GitLab Deployments:
Linux packages verschiedener Distributionen - sehr aufwändig!
Kubernetes Vorlagen: Helm Chart oder über K8s Operator patterns
Docker aka Container (Linux) - meistens meine Go to Solution
Alles selbst kompilieren (!!)
Heutzutage verstehen manche Firmen auch ihre Cloud als Premise. In solchen Fällen könnte man zu Lösungen bei AWS, Google Cloud Platform oder Azure greifen.
Für mich bedeutet on-Premise, dass die Technik in meine - lokal nutzbaren - Infrastruktur verfügbar ist.
Hinweis
Lösungen unter Windows oder auch mit Docker für Windows werden ausdrücklich nicht empfohlen bzw. ausgeschlossen.
Der GitLab Container ist ein atypisches Prozessmonster! Der Container beinhaltet alle Dienste: SSH, Redis, Postgres und alle GitLab-Dienste! Anm.: gut über 100 Prozesse statt sonst Einem Prozess!
GitLab LXC¶
Es folgt eine Schnellanleitung - eine Art Kompression der GitLab Anleitungen - für die Bereitstellung von GitLab in einem LXC Container.
Vorbereitung LXC Debian:
ProxmoxVE Server
LXC Container (z.B. Debian 12 Bookworm); Empfehlung: min. 8 GiB RAM, ausreichend Datenträger +50 GiB; für den späteren Systemstart ausreichend Zeit beachten!
Docker Engine installieren / testen
Variable für Docker Compose Yaml bereitstellen mit
export GITLAB_HOME=/srv/gitlab
und testenGitLab Homedir für Docker Volumes erstellen:
mkdir -p /srv/gitlab
SSH Port LXC Container ändern
Wir legen den Standard SSH Port für den LXC Container auf 2424, damit spätere Git/SSH Zugriffe auf Standardport 22 funktionieren.
Anpassung in /etc/ssh/sshd_config
: Port 2424
Da wir es mit einem LXC-Container zu tun haben, müssen wir etwas tricksen.
systemctl disable ssh.socket
systemctl enable ssh
reboot
Testen des geänderten Ports für Standard-SSH auf LXC Container:
# LXC - Server
ss -tlpn
# Client
ssh user@lxcmachine -p 2424
Bereitstellung GitLab Container
Übersicht über verfügbare GitLab Docker Images (Tags): https://hub.docker.com/r/gitlab/gitlab-ce/tags
Beispiel für Docker Compose YAML Datei mit Image gitlab/gitlab-ce:17.5.1-ce.0:
Compose Datei (z. B.): /root/gitlab/docker-compose.yml
---
services:
gitlab:
image: gitlab/gitlab-ce:17.5.1-ce.0
container_name: gitlab
restart: always
hostname: 'gitlab.example.com'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://gitlab.example.com:8929'
gitlab_rails['gitlab_shell_ssh_port'] = 22
ports:
- '8929:8929'
- '443:443'
- '22:22'
volumes:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
shm_size: '256m'
Die Umgebung wird mit docker compose up -d
gestartet und mit
docker compose down
beendet.
Anmerkungen zur Docker Compose Datei:
Hostname bitte per DNS oder /etc/hosts verfügbar machen
GitLab Admin-Oberfläche extern:intern auf Port 8929
GitLab SSH extern:intern auf Port 22
https vorbereitet
Volumens: Unterordner in $GITLAB_HOME werden automatisch erstellt
Der GitLab Container enthält ein vordefiniertes zufälliges Passwort
für den root-User in Datei /etc/gitlab/initial_root_password
.
Wir lassen uns die fragliche Datei anzeigen:
docker exec -it gitlab cat /etc/gitlab/initial_root_password
Das Passwort findet sich in der Zeile mit
Password: qvOJKiryU0FvwjpEeL8vu2rpsZBO2cNAOqRDQTEavCA=
.
Wir sollten uns über http://gitlab.example.com:8929
jetzt mit
Benutzer root und dem Initial Passwort einloggen können.
Gefahr
Bitte als erstes die außeren freien Registrierungen und Anmeldungen am Portal untebinden!
Anleitungen für GitLab Passwort Reset: https://docs.gitlab.com/ee/security/reset_user_password.html
Linksammlung¶

Bookmarks - Bild: markus-winkler-qg9JEHiPX98-unsplash.jpgg¶
To-Do: Zusammenstellung der üblichen Verdächtigen - also von wiederkehrenden Adressen mit wertigen Infos zu Git. Und Google liefert sicherlich gerne weitere Quellen, Hilfen und Portale ;-)
Zur Einführung ein paar gestreute Git-Links:
Git¶
Das Logo für Git ist in der Git Dokumentation in verschiedenen Versionen verfügbar. Git ist eine der am Besten dokumentierten Werkzeugkisten in der IT.

Full color Git logo for light backgrounds¶
Git Logo
Erste schnelle Übersicht Git:
Grafikoberflächen Git

Lazygit - A simple terminal UI for git commands¶
Git Repos¶
Wir starten mit dem Klassenprimus GitHub. Einer der Gründer (Scott Chacon) ist auch für das Git Book verantwortlich. Im Jahr 2018 wurde das Portal von Microsoft gekauft.

GitHub Portal (Screenshot 2024)¶
GitHub
GitLab
… todo …
Codeberg
… todo …
Gitea
… todo …
Tutorials¶
Falls wir noch mal Anregungen benötigen, warum wir definitiv Git brauchen mal eine Anregung von Jorge Cham aus einem seiner PHD Comics.

Piled Higher and Deeper by Jorge Cham, http://www.phdcomics.com/comics/archive_print.php?comicid=1531¶
Diverse Anleitungen
Mittwald (Tutorials)
Reproducible Research Tech - Session 4: Version Control with git and GitHub
Learn Microsoft Portal - Introduction to version control with Git (4 Modules)
Opensource.com - Git - Übersicht Git Tutorials, Tipps & Tricks

Opensource.com - Git Tutorials, Tipps & Tricks¶
Cheats¶
Diverse Versionen für TN bereitgestellt. Über das git-scm.com-Portal ist diese Online-Version eines Git-Cheat-Sheet zur Verfügung gestellt: git-scm.com Online Cheat Sheet

ndpsoftware.com - git-scm.com Online Cheat Sheet¶
Cheat Sheet
Verschiedenes¶
Workflows
Merge vs. Rebase
Specials
Literatur¶
Bücher zum Thema GIT gibt es tatsächlich einige. Und ich will an dieser Stelle nur eine kleine eigene Übersicht anhängen.

Books - Bild: matthew-feeney-Nwkh-n6l25w-unsplash.jpg¶
Die folgenden Git Bücher liefern die Schwerpunkte zur Seminarpraxis und den Übungen.
Hinweis
Texte und Anmerkungen zu den Büchern von Amazon bzw. den Verlagen.
Des Weiteren sind einige Abbildungen dargestellt und verlinkt worden. Und los geht es…
Git - Rheinwerk Verlag¶
Projektverwaltung für Entwickler und DevOps-Teams von Bernd Öggl, Michael Kofler
Auch als englische Version Project Management for Developers and DevOps Teams verfügbar.
Git in der Praxis
Daten für die 2. Auflage:
Herausgeber: Rheinwerk Computing; 2. Edition (5. Mai 2022)
Sprache: Deutsch
Gebundene Ausgabe: 423 Seiten
ISBN-10: 3836288451
ISBN-13: 978-3836288453
Abmessungen: 17.9 x 3 x 24.9 cm
Git gehört zum unverzichtbaren Handwerkszeug aller IT-Profis und darf in keiner Toolbox fehlen. Dabei macht es keinen Unterschied, ob Sie Konfigurationsdateien versionieren wollen, an Open-Source-Projekten mitarbeiten oder im Team komplexe Anwendungen entwickeln: Git sorgt dafür, dass Sie den Überblick behalten.
Daher lernen Sie hier nicht nur, wie Sie Änderungen einchecken und fremde Repositorien klonen, sondern erfahren, wie Git Ihnen den Arbeitsalltag leichter macht.

Git in der Praxis (Rheinwerkverlag) - Kofler, Öggl (1. Auflage - Vorderseite)¶
Aus dem Inhalt:
Git in zehn Minuten: der Schnelleinstieg
Installation und Einrichtung
Grundlagen: Repos, Commits, Branches, Merging
GitLab: Projekte lokal hosten
GitHub: der Marktplatz für Softwareprojekte
GitHub-Alternativen: Bitbucket, Azure DevOps Services, Gitolite und mehr
Arbeitstechniken: History, Feature Branches, Stashing, Hooks und mehr
Workflows: So nutzen Sie Git effektiv
Best Practices und Troubleshooting
Kommandoreferenz

Git in der Praxis (Rheinwerkverlag) - Kofler, Öggl (1. Auflage - Rückseite)¶
Das Git-Buch¶
Git: Verteilte Versionsverwaltung für Code und Dokumente
Git: Verteilte Versionsverwaltung für Code und Dokumente
Taschenbuch: 336 Seiten
Verlag: Open Source Press; Auflage: 2 (1. November 2014)
Sprache: Deutsch
ISBN-10: 3955391191
ISBN-13: 978-3955391195
Verpackungsabmessungen: 23,8 x 17,6 x 1,8 cm
Gerne auch online: Das Git-Buch
Über den Autor und weitere Mitwirkende
Valentin Haenel ist Software-Entwickler und lebt in Berlin. Er hat sich auf Algorithmen, Kompressionsverfahren und Datenanalyse spezialisiert und betreibt sowohl beruflich als auch privat Open-Source-Entwicklung. Git ist seit 2008 sein Mittel der Wahl für die Versionsverwaltung.
Julius Plenz studiert Mathematik an der Freien Universität Berlin. Er veranstaltet regelmäßig Vorträge und Workshops zu Unix-Themen und ist Autor eines Buches über die Z-Shell. Bei seiner Arbeit am Rechenzentrum der FU Berlin wie auch privat setzt er Git täglich ein.

Git: Verteilte Versionsverwaltung für Code und Dokumente¶
Linus Torvalds begann mit der Entwicklung von Git, um die Quellen des Linux-Kernels zu verwalten. Heute ist es das meistverwendete Versionskontrollsystem für Open-Source-Software und erfreut sich auch im Firmenumfeld großer Beliebtheit.
Das vorliegende Buch führt Sie auch in dieser aktualisierten, 2. Auflage fundiert und mit zahlreichen Beispielen in die Benutzung von Git und alle relevanten Techniken ein, die im täglichen Umgang mit der Versionsverwaltung zum Einsatz kommen. Sie lernen die Modellierung eines Repositorys als Graph von Commits und damit die Grundlage für fortgeschrittene Konzepte kennen: Merge-Strategien, automatisierte Fehlersuche, Umstiegsszenarien (Subversion-Migration zu Git). Hinzu kommen die Besonderheiten dezentraler Arbeitsabläufe und deren Einfluss auf den Workflow von Projekten.
Umfang der Darstellung und Erfahrung der beiden Autoren machen das Buch zu einer unverzichtbaren Hilfe bei der Arbeit mit der modernen Versionsverwaltungssoftware.
Pro Git¶
Anm.: english; written by Git pros Scott Chacon and Ben Straub
Pro Git - Everything you need to know about Git
Pro Git - Everything you need to know about Git
Taschenbuch: 456 Seiten
Verlag: Apress; Auflage: 2nd ed. (9. November 2014)
Sprache: Englisch
ISBN-10: 9781484200773
ISBN-13: 978-1484200773
ASIN: 1484200772
Größe und/oder Gewicht: 19,1 x 2,6 x 23,5 cm
Gerne auch online: Pro Git
Pro Git (Second Edition) is your fully-updated guide to Git and its usage in the modern world. Git has come a long way since it was first developed by Linus Torvalds for Linux kernel development. It has taken the open source world by storm since its inception in 2005, and this book teaches you how to use it like a pro.

Pro Git - Everything you need to know about Git¶
Effective and well-implemented version control is a necessity for successful web projects, whether large or small. With this book you’ll learn how to master the world of distributed version workflow, use the distributed features of Git to the full, and extend Git to meet your every need.
Written by Git pros Scott Chacon and Ben Straub, Pro Git (Second Edition) builds on the hugely successful first edition, and is now fully updated for Git version 2.0, as well as including an indispensable chapter on GitHub. It’s the best book for all your Git needs.
Versionsverwaltung mit Git¶
Anm.: deutsch; geschrieben von Sujeevan Vijayakumaran
Versionsverwaltung mit Git
Versionsverwaltung mit Git
Broschiert: 288 Seiten
Verlag: mitp; Auflage: 2. überarbeitete Auflage 2019 (15. Mai 2019)
Sprache: Deutsch
ISBN-10: 3747500420
ISBN-13: 978-3747500422
Autor online: Sujeevan Vijayakumaran
Von grundlegenden Funktionen über die Handhabung von Branches und Remote-Repositorys bis zu Tipps und Tricks für (nicht nur) alltägliche Funktionen
Auswahl sinnvoller Workflows und Einsatz für Teams
Git-Repositorys hosten mit GitHub und GitLab
Git ist in der Softwareentwicklung bereits weit verbreitet sowohl in Firmen als auch in Open-Source-Projekten. Zum Einstieg lernen Anfänger häufig nur die wichtigsten Befehle, die schnell nicht mehr ausreichen, vor allem wenn die ersten Fehler auftreten.
Dieses Buch behandelt einerseits die gängigen Befehle, die Sie beim täglichen Arbeiten mit Git brauchen. Andererseits geht es dem Autor auch darum, dass Sie Git als Ganzes verstehen, um es effektiv im Entwicklungsprozess einsetzen zu können. … (mehr auf Verlagsseiten zum Buch)

Versionsverwaltung mit Git (Cover)¶
Aus dem Inhalt:
Konfiguration
Arbeiten mit Branches
Verteilte Repositorys
Hosting mit GitHub und GitLab
Workflows
Hooks
Umstieg von Subversion
Zahlreiche Tipps für die tägliche Arbeit
Grafische Clients
Tipps für nachvollziehbare Git-Historien
Frequently Asked Questions
Befehlsreferenz

Versionsverwaltung mit Git (Backcover)¶
reStructuredText¶
Hier folgen abschließend noch die Meta-Infos zur Dokumentenversionspflege mit Hilfe von restructuredText:

restructuredText auf Wikipedia¶
Kurzinfo auf Wikipedia zu rST
reStructuredText (kurz ReST, reST oder RST) ist eine vereinfachte Auszeichnungssprache (Markup) mit dem Ziel, in der reinen Textform besonders lesbar zu sein.
Die reST-Dokumenten lassen sich nahezu beliebig in gewünschte Formate wandeln:
ODT - OASIS Open Document Format for Office Applications
Kurzform: OpenDocument, ODF – engl. Offenes Dokumentformat für Büroanwendungen
Textformate wie für LibreOffice, Microsoft Word
HTML - diverse HTML-Varianten (Websitestile)
LaTex
professioneller Schriftsatz mit Exportmöglichkeiten nach PostScript und PDF
PDF (bzw. PostScript)
Epub - Standard für eBooks
Desweiteren lassen sich die Dokumente
professionell verlinken (taggen)
indizieren und
durchsuchen.
Tipp
Microsoft VS Code Settings in .vscode/settings.json
für Live-Preview:
{
"esbonio.sphinx.confDir": "${workspaceFolder}",
"esbonio.sphinx.buildDir": "${workspaceFolder}/_build",
"restructuredtext.linter.run": "off"
}
Wichtig ist die Zeile für den _build Pfad!
Weiter Infos zur verwendeten Sphinx/reStructuredText Technik folgen.
Sphinx Vorlage TYPO3¶

TYPO3 Sphinx reStructuredText Technik¶
Für dieses Dokument nutze ich eine modifizierte Sphinx Vorlage aus dem Hause TYPO3:
Leider kann man ohne die Dev-Umgebung für die TYPO3-Dokumentation nicht alle Stilmittel direkt nutzen. Diese Umgebung liegt natürlich auch wieder als Container-Lösung vor!
Bildinfos¶
Alle Bildmaterialien in dieser Ausarbeitung wurden nach bestem Wissen recherchiert und sind gemäß ihrer geforderten Bedingungen hinsichtlich des Autors kommentiert.

Unsplash.com - Freie Bilder¶
Die entsprechenden Bildmaterialien entstammen folgenden Quellen:
Eigene Bildmaterialien
oder Bildkompositionen
Wikipedia
Link zum Wikipedia Bild (inkl. Autorennennung)
Für die Verwendung anderer freier Ressourcen folgen noch weitere Erläuterungen.
Unsplash¶
Aus dieser Quelle werden alle Bildmaterialien mit Bildname attributisiert.
Erklärung zum Bildcode:
Info |
Inhalt |
---|---|
Bildname |
magnet-me-beCkhUB5aIA-unsplash.jpg |
Unsplash Autor |
magnet-me |
Bildcode |
beCkhUB5aIA |
Aus dem Unsplash-Bild-Code (hier: beCkhUB5aIA) lässt sich der Bildlink zum Unsplash-Portal zusammenbauen:
https: // unsplash.com / photos / Bildcode
https: // unsplash.com / photos / beCkhUB5aIA
Abweichende Bild-Quellen wurden entsprechend kommentiert/dokumentiert.
Pexels - Pixabay¶
Neben der von mir sehr geschätzten Unsplash-Community nutze ich auch noch die Pexels - Pixabay Angebote.

Pexels (and Pixabay) License free¶
Lizenzinfos
Link zur Pexels FAQ Are the photos and videos on Pexels really free? und auch für Pixaby - Zusammenfassung der Inhaltslizenz
Die genutzten Fotos werden von mir mit ihren Originallinks hinterlegt.
Die Community ist insbesondere bei Affinity Software (Photo, Publisher, Designer) als Palette (Stock) eingebunden. Das ermöglicht mir in vielen Fällen eine sehr schnelle Recherche.
Tipp
Im Netz gibt es aktuelle Anleitungen, in denen die Installation über spezielle abgespeckte WINE Umgebungen unter Linux für die Affinity Software gezeigt wird!
Dokumentstatus¶

Status des Git-reStructuredText Projekts: In Arbeit (Bild: richy-great-MAYEkmn7G6E-unsplash.jpg)¶
Meine inhaltlichen Aufbereitungen zu den diversen Themen unterliegen ständigen Änderungen und Aktualisierungen.
Bemerkung
Diese Dokument befindet sich in stetiger Überarbeitung. Fehlerbereinigung (Typos) oder eine ggf. noch fehlende Indexierung der Dokumente ist ein Work in Progress und findet auch in Seminaren statt.
Fragen Sie also gerne auch einmal später nach einer aktualisierten Variante dieser Ausarbeitung und beziehen sich dabei bitte auf die entsprechende Versionsnummer des Dokuments (oder der angegebenen Versionierung).
To-Do¶
Eine - nicht immer aktuelle - Liste mit Planungen für Arbeiten an dieser Dokumentation.

To Do List - Work in Progress (Pic: thomas-bormans-pcpsVsyFp_s-unsplash)¶
Zu tun
[Always] Korrekturen / kleine Verbesserungen
[Always] Einbau weiterer Tipps & Tricks rund um Git
[Always] Optimierung Styling HTML
[Always] Optimierung LaTeX / PDF: Styling und Textfluss
Git Worktree ..
…
Alles wie immer: Work in progress…
Version¶
Versionierungsmerkmale für die reST-Dokumentstrukturen
Hier folgen jetzt Meta-Infos zur Dokumentenversionspflege:
- Version:
2.0
- Language:
de
- Description:
Unterlagen zu Git Seminaren Trainer Joe Brandes.
Erstellt mit restructuredText / Sphinx / ReadTheDocs / sphinx_typo3_theme v4.9.0
- Keywords:
Git, Seminarunterlage, Trainer Joe Brandes
- Copyright:
Joe Brandes
- Author:
Joe Brandes
- License:
GNU General Public License, either version 2 of the License or any later version.
- Rendered:
31.10.2024