Git Seminar

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

Git Website Screenshot 2023

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

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

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

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

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 ermitteln
$ 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 Konfiguration (kurze Version - ohne Quellen)
$ 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 Konfiguration (lange Version - mit Quellen)
$ 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

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 Repo

  • git 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

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:

Analyse als Kommentierungen zu den Ausgabezeilen von git status -s
$ 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 mit Rückmeldungen zum LineFeed Verhalten - sonst Leer!
$ 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:

  1. Lokale Datei im Git-Ordner - aktuellste (lokale) Bearbeitung: 4 Zeilen

  2. Datei im Index (Staging Area) - nach letztem git add: 3 Zeilen

  3. 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:

  1. 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!
    
  2. 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!
    
  3. 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 Repo

  • git 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)

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)

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

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

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!

Tags

Tags gibt es in zwei grundsätzlichen Varianten:

  • Annotated Tags - Tags mit Anmerkungen; wird auch als Objekt in Git abgelegt

  • Lightweight Tags - ohne Anmerkungen; einfach nur eine Referenz im Ordner /tags

Um Commits anzusprechen nutzt man ihre (abgekürzten) SHA-1-Summen. Diese Bezeichner lassen sich aber schlecht verinnerlichen / merken.

Hinweis

Tags sind - im Gegensatz zu Branches oder HEAD - statisch!

Die Anmerkungen für Annotated Tags (können) beinhalten:

  • Autor

  • Beschreibung

  • GPG Signatur

  • und natürlich Referenz auf markiertes Objekt

Basisbefehl: git tag (listet alle Tags)

Nur spezielle Tags filtern und anzeigen: (hier: Git-Repo)

$ git tag --list v0.*
...
$ git show v0.99 | head -20
tag v0.99

Test-release for wider distribution.

I'll make the first public RPM's etc, thus the tag.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBC0b9oF3YsRnbiHLsRAlUUAKCJEyvw8tewGFKd/A3aCd82Wi/zAgCgl7z4
GYPjO+Xio0IvuEYsrhFc2KI=
=TVVN
-----END PGP SIGNATURE-----

commit a3eb250f996bf5e12376ec88622c4ccaabf20ea8
Author: Junio C Hamano <junkio@cox.net>
Date:   Sun Jul 10 15:40:43 2005 -0700

    [PATCH] alternate object store and fsck

    The location alt_odb[j].name[0..] is filled with ??/?{38} to form a sha1

Man sieht hier den Commit a3eb250f996bf5e12376ec88622c4ccaabf20ea8 auf den referenziert wurde.

Lightweight Tags erstellen

Einfach nur: git tag tagname erstellt Lightweight Tag auf HEAD.

Aber natürlich kann man beliebige tagname nutzen: Commits-SHA-1, master oder HEAD~…

Annotated Tags erstellen

Sollte man für öffentliche Git-Repos bevorzugen!

Hinweis

Tags werden nicht automatisch in öffentliche Repos gepusht - hierzu später mehr, wenn es dann um Remote Repositorys geht.

Hier - wie beim Commiten - die Tag-Beschreibung mit -m ergänzen: git tag -m "Erste Veröffentlichung" v0.2

Für die Signierung von Tags nutzt man -s (Anm.: entsprechend eigene Signaturen vorausgesetzt)

Für die Überprüfung von signierten Tags nutzt man -v: git tag -v v1.7.1 (hier wieder Git-Repo und den bereits importierten Schlüssel des Signierenden vorausgesetzt).

Tags auflisten

Am einfachsten mit git tag (Short-Form)

Etwas ausführlicher: git tag -n (Anzahl von Zeilen zum Tag auflisten -n<x>)

Mit Infos zu den Tag-Objekten und verknüpften Commits: git show-ref --tags -d

Oder versuchen mit git show --name-only <tagname> (Infos zu Tagname)

Tags löschen

Man löscht Tags mit -d: git tag -d tagname

Gefahr

Beim Veröffentlichen von Tags muss man darauf achten, dass sie nicht auf unterschiedliche Objekte referenzieren!

Non-Commit Tags

Die Tags können auf beliebige Objekte referenzieren - also nicht nur auf Commits, sondern auch auf Dateien.

Wir erinnnern uns: Dateien werden als Blog-Objekte im Git abgelegt. Also einfach einen Tag auf die SHA-1-Summe (den Objekt-Bezeichner) für die gewünschte Datei (bzw. den Dateizustand) referenzieren.

Der Chef-Git-Entwickler hat seine GPG-Pub-Datei ins Git gelegt und mit dem Tag junio-gpg-pub referenziert.

$ git show junio-gpg-pub | head -15
tag junio-gpg-pub
Tagger: Junio C Hamano <gitster@pobox.com>
Date:   Thu Nov 20 15:12:15 2014 -0800

GPG key to sign git.git archive

This blob contains the GPG public key I use to sign git.git archive.

To use it to verify tags I signed, do:

  $ git-cat-file blob junio-gpg-pub | gpg --import

to import it into your keyring, and then

  $ git-tag -v $tag_to_be_verified
...

Tags - pull/push

Bereits veröffentlichte Tags werden automatisch mit einem git pull heruntergeladen.

Für das Veröffentlichen: git push origin v0.2

git describe

Mit dem Aufruf git describe bzw. git describe --tags erhält man eine Beschreibung für den aktuellen Tag und seinen Abstand zum Commit nach dem folgenden -g: (hier wieder für das Git-Git ;-)

$ git describe
v2.22.0-545-g9c9b961d7e

Aktueller Tag also v2.22.0 und man ist 545 Positionen vom SHA-1 9c9b961d7e entfernt.

Git Describe (grafisch - Git Gui)

Git Describe (grafisch - Git Gui)

Etwas praxirelevanter: ein Commit 28ba96a vom 23.04.2010

$ git describe --tags 28ba96a
v1.7.1-7-g28ba96ab27

Dieser Tag hat 7 Positionen Differenz zum (vorherigen) Tag v1.7.1!

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 überschreiben

  • mit -d einen Branch löschen; mittels -D auch wenn ggf. noch Dinge uncommited oder unveröffentlicht

  • mit -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!)

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.pl - Version 01
# Hello World! in Perl
print "Hello World!\n";

Wird geändert zu:

hello.pl - Version 02
#!/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

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)

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

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)

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.

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:

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?

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?

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

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

Zwei Branches vor FF-Merge

Wenn man jetzt git merge durchführt erhält man:

Zwei Branches nach FF-Merge

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

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

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

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

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

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 und git 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

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 Branches

  • git branch -r - Remote Branches

  • git 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

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)

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)

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 (gitbu.ch)

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

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

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

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 testen

  • GitLab 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 - Unsplash.com

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

Full color Git logo for light backgrounds

Git Logo

Erste schnelle Übersicht Git:

Grafikoberflächen Git

Lazygit - A simple terminal UI for git commands

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 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

Piled Higher and Deeper by Jorge Cham, http://www.phdcomics.com/comics/archive_print.php?comicid=1531

Diverse Anleitungen

Opensource.com - Git - Übersicht Git Tutorials, Tipps & Tricks

Opensource.com - 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

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 - Unsplash.com

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)

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)

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

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

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)

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)

Versionsverwaltung mit Git (Backcover)

reStructuredText

Hier folgen abschließend noch die Meta-Infos zur Dokumentenversionspflege mit Hilfe von restructuredText:

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.

Wikipedia - restructuredText

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

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

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:

Bildcode Unsplash

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

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)

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)

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