Git
Versionsverwaltung (VCS – Version Control System)
Üblicherweise wird eine Software bei der Entwicklung und Wartung versioniert. Hierbei wird ein VCS eingesetzt, dass folgende Möglichkeiten bietet:
-
Archivierung aller Projektstände, um bei versehentlichen Änderungen diese zur Wiederherstellung rückgängig machen zu können.
-
Koordinierung des gemeinsamen Zugriffs im Entwicklungsteam auf den Quellcode. Dabei werden Änderungen namentlich protokolliert.
-
Gleichzeitiges Arbeiten an mehreren Entwicklungszweigen (engl. Branches) eines Projekts, z.B. Produktion und Developement.
Git

ist
ein freies, weitverbreitetes VCS, dessen Entwicklung von Linus
Thorwalds 2005 initiiert wurde. https://git-scm.com/
Beispielhaft wird hier mittels der Konsole (bash) die Arbeitsweise im Einzelnen vorgestellt, um die Abläufe transparent zu machen:
Git Bash starten
Um die Arbeitsweise von und mit Git besser zu verstehen, arbeiten wir nicht mit einer GUI sondern mit der Bash. Hier werden die Befehle manuell eingegeben was ein tieferes Verständnis erfordert.
Git konfigurieren
Nach der lokalen Installation von Git werden die wichtigsten Einstellungen einmalig für alle Projekte vorgenommen:
$ git config --global user.name "Vorname Nachname"
$ git config --global user.email user@mydomain.com
Lokales Repository anlegen
Es wird zunächst ein leeres Repository (engl. Speicher) mit Namen „Test“ angelegt:
git init Test
Ein Verzeichnis Test wird angelegt. In ihm befindet sich ein Unterverzeichnis .git
In ihm werden alle Systeminformationen dieses Repositories gespeichert. (Es ist ein verstecktes Systemverzeichnis und kann nur durch Aktivieren der entsprechenden Ordneroption sichtbar gemacht werden.)
Datei in Repository aufnehmen
Testweise wird eine Datei „first.txt“ mit etwas Text angelegt.
git status
informiert
darüber,
dass die Datei von Git
noch nicht verfolgt (untracked file)
wird. Dafür
muss sie zunächst zum
Index (sog. stage) hinzugefügt
werden:
git add first.txt
(Alternativ können auch Platzhalter wie
z.B. git
add *.txt
verwendet werden. Ein einzelner
Punkt weist GIT an, alle Dateien hinzuzufügen: git
add .)
git status
besagt nun, dass neue Datei hinzugefügt und zum Repository hinzugefügt werden kann.
Jetzt kann die Datei an das System übergeben werden:
git commit -m 'erste Projektversion'
Abbildung 2: Dateien dem Repository hinzufügen
git status
zeigt jetzt an, dass das nichts weiter zum Repository hinzugefügt werden muss.3

Abbildung 3: 1. Commit
Standardmäßig erhält der
Versionszweig den Namen „main“. (Die frühere Bezeichnung „master“ wurde aus Gründen der political correctness abgelegt.)
HEAD (Großschreibung
beachten!) weist auf die aktuelle Version. Git verwendet keine
fortlaufenden Nummern zur internen Verwaltung, sondern einen
Hash-Wert, der Änderungen zum vorhergehenden Commit (der Einfachheit
halber nur die ersten 4 Zeichen dargestellt).
Änderungen in Repository einpflegen
Wir legen nun einen Unterorder „subfolder“ mit einer darin befindlichen Datei „second.txt“ mit folgendem Inhalt an:
erste Zeile
zweite Zeile
dritte Zeile
Auch den Text in first.txt verändern wir.
git status
weist uns an, die modifizierte Datei „first.txt“ und die noch nicht verfolgten Dateien in „subfolder“ hinzuzufügen, damit ein Commit diese einschließt:
git add .
fügt
alle neuen und geänderten Dateien hinzu.
(git add *.txt
würde
die Dateien im Unterverzeichnis „subfolder“ nicht
miteinbeziehen)
git commit -m 'zweite Projektversion'
pflegt
die Änderungen im Repository ein.

Abbildung 4: Repository nach dem 2. Commit
Der 2. Commit verweist auf den ersten.
Vorherige Version wiederherstellen
Mit einem Checkout lassen sich einzelne Dateien oder ganze komplette Programmversionen wiederherstellen.
Die Historie wird angezeigt, um die Hash-Werte anzuzeigen:
git log --graph --full-history --all
* commit b5c9d0e8abe60a5589cb24e52d87e183ac2265de
| Author: Vorname Nachname <user@mydomain.com>
| Date: Thu May 26 11:43:17 2016 +0200
|
| zweite Projektversion
|
* fc3929931d94c232605155280cfb2bc6a53befac
Author: Vorname Nachname <user@mydomain.com>
Date: Thu May 26 10:22:47 2016 +0200
erste Projektversion
Ein Checkout lässt sich dann z.B. wie folgt machen.
git checkout fc3929931d94c232605155280cfb2bc6a53befac

Abbildung
5: HEAD nach 1. checkout
Das Arbeitsverzeichnis ist nun im Zustand direkt nach dem 1. Commit.
Zurückgeschaltet
zum main branch wird mit
git checkout main
Programmversion verzweigen
Beispielhaft wird aus der produktiven main-Version zum Entfernen eines Bugs in die bugfix-Version verzweigt:
Parameter -b steht für branch (engl. Zweig)
git checkout -b bugfix

Abbildung
6: Versionsverzweigung nach checkout
Der Code in „second.txt“ wird nun verändert:
erste Zeile
zweite Zeile geändert (bugfix)
dritte Zeile
Die modifizierte Datei wird hinzugefügt und in das Repository eingepflegt:
git commit -am 'Bug gefixed'
(Der Parameter -a (add) bewirkt, dass
alle Dateien erst hinzugefügt und dann im Repository gespeichert
werden.)

Abbildung 7: nach dem 3. Commit im branch bugfix
Aber oft hat ein anderer Entwickler in der Zwischenzeit am main branch in der gleichen Datei weitergearbeitet. Er hat den Code in „second.txt“ wie folgt geändert:
erste Zeile
zweite Zeile geändert (main)
dritte Zeile
Wir simulieren das, in dem wir nach main schalten, die Änderung einpflegen und speichern:
git checkout main
Änderung einpflegen
git commit -am 'dritte Programmversion'

Abbildung 8: Zwischenzeitliche Änderung im main branch
Programmzweige wieder zusammenführen
Der Bug ist beseitigt dieser Zweig muss jetzt allerdings in den produktiven main-Zweig integriert werden. Dafür muss erst zum main branch geschaltet werden, falls noch nicht geschehen:
git checkout main
Danach folgt die Integration:
git merge bugfix
Weil die gleiche Zeile in unterschiedlichen branches geändert wurde, gibt es dabei einen Konflikt der manuell behoben werden muss. Der Inhalt von „second.txt“ ist:
erste Zeile
<<<<<<< HEAD
zweite Zeile geändert (main)
=======
zweite Zeile geändert (bugfix)
>>>>>>> bugfix
dritte Zeile
Der
Abschnitt zwischen <<<<<<<
HEAD und
=======
sind
die Änderungen des main branch. Es wurde mittels checkout vor dem
Merging ja in diesen Zweig umgeschaltet. Der Teil darunter bis zu
>>>>>>>
bugfix
bezeichnet
die Änderungen des bugfix branch.
Um den Konflikt zu lösen, entscheidet man sich für einen der beiden Teile oder ersetzt den ganzen Abschnitt komplett.
Danach
wird die Datei eingecheckt:
git commit -am 'vierte Programmversion (Bug gefixed)'

Abbildung 9: Nach dem Merging
Branch löschen
git log --graph --full-history --all
Es ist möglich, den Aufruf langer
Befehle durch die eigene Definition eines Alias zu
vereinfachen.
Empfohlene Definition des Alias „tree“
git config --global alias.tree 'log --graph --all –-pretty=oneline
--abbrev-commit --decorate'
Aufruf:
git tree
--graph
erstellt mittels ASCII-Art eine grafische Darstellung der
Branches.
--all
sorgt dafür, dass auch andere Branches angezeigt werden (z.B. in
Abb. 8, würde ohne --all
der 3. Commit nicht angezeigt werden).
--pretty=oneline
stellt jeden Commit in nur einer Zeile dar; dies erhöht die
Übersicht erheblich, besonders wenn man mehr als ein paar Commits
hat.
--abbrev-commit
kürzt die Hashwerte der Commits von 40 auf 7 Zeichen, da man den
kompletten Hashwert eigentlich nie braucht.
--decorate
fügt einige Marker ein, die einem anzeigen, welcher Branch auf
welchen Commit zeigt.
Der Branch bugfix kann nun gelöscht werden:
git branch -d bugfix
Vorgehensweise beim Verzweigen und Zusammenführen von Programmversionen
Die Vorgehensweise bei der Arbeit mit Git muss im Team abgesprochen werden.
Vincent Driessen schlägt folgende Strukturen vor:

Eine mögliche Vorgehensweise beim Verzweigen und Zusammenführen nach https://nvie.com/posts/a-successful-git-branching-model/ (31.08.2021)
Externes Repository anbinden
Um im Team an einer Codebasis arbeiten zu können, muss der Code mit einem Remote Repository synchronisiert werden.
https://git-scm.com/book/de/v1/Los-geht%E2%80%99s-Wozu-Versionskontrolle%3F (27.05.2016)

Abbildung 10: Anbindung an Server
Es empfiehlt sich, sich testweise bei Github anzumelden und ein Repository einzurichten.
Das Anlegen von öffentlichen und privaten Repositories bei Github ist in bestimmten Grenzen kostenfrei. Der Account kann später wieder gelöscht werden. https://github.com/
Remote Repository hinzufügen:
git remote add origin https://github.com/ateachment/test.git
origin ist dabei der Kurzname der bei Git standardmäßig für den Server
vergeben wird.
Eventuell muss ein Proxy konfiguriert werden:
git config --global http.proxy https://172.22.100.2:443
oder falls der WvS-Proxy so nicht funktioniert, dann halt ausnahmsweise unverschlüsselt
git remote rm origin # erst wieder remove origin
git remote add origin http://github.com/ateachment/test.git # kein https
git config --global http.proxy http://172.22.100.2:80 # Port 80
Angebundene remote repositories können angezeigt werden mit:
git remote -v
Änderungen in ein Remote Repository hochladen
Nachdem
die Anbindung erfolgt ist, kann
nun ein Branch
ins Remote Repository hochgeladen werden. Dafür muss man sich bei Github ein Personal Access Token PAT erzeugen (Die Kennwortauthentifizierung wurde Github zu unsicher.). Auf github.com navigiert man über Settings => Developer Settings => Personal access tokens generiert dort ein neues PAT und konfiguriert folgende Berechtigungen
workflow
write:packages
delete:packages
Kopieren Sie das PAT an einen sicheren Ort.
git push origin main
lädt nun die Branch in das Repository hoch. Die Eingabe des Personal Access Tokens muss nun manuell vorgenommen werden.
Es geht auch in einem Schritt direkt von der Kommandozeile mit:
git push https://<GITHUB_ACCESS_TOKEN>@github.com/<GITHUB_USERNAME>/<REPOSITORY_NAME>.git
(Großgeschriebene Bezeichnungen mit persönlichem PAT, Benutzernamen und Repository-Namen ersetzen.)
https://techglimpse.com/git-push-github-token-based-passwordless/ (07.09.2021)
Remote Repository klonen
Andere Entwickler können nun das Repository klonen:
git clone https://github.com/ateachment/test.git
Änderungen aus dem Remote Repository herunterladen und zusammenführen
Änderungen aus dem vormals geklonten Repository werden heruntergeladen mit:
git fetch origin
Diese Änderungen müssen dann mit eventuellen eigenen Änderungen noch manuell zusammen geführt werden.
Um das Herunterladen gleich mit einem Merging zu verbinden, benutzt man:
git pull origin
Dateien und Verzeichnisse von der Synchronisation ausschließen
Natürlich sollte binäre Dateien oder z.B. Konfigurationsdateien der IDE von der Synchronisation ausgeschlossen werden. Dies geschieht mittels einer Datei mit der Bezeichnung „.gitignore“ im Projektverzeichnis.
Das Erstellen dieser .gitignore-Datei kann sehr aufwändig werden. Fertige Dateien sind im WWW erhältlich, z.B. hier für Visual Studio: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore (14.08.2018)
Versionsnummern vergeben
Wichtige Versionsstände, wie z.B. Releases, sollten durch eine Versionsnummer markiert werden, was die Verwaltung der Commits erleichtert.13
git tag v0.0.1
Weitere Möglichkeiten des Tagging: https://git-scm.com/book/de/v1/Git-Grundlagen-Tags (14.08.2018)
Danksagung
Dank
gilt den Schülern der Klasse FI4E der Werner-von-Siemens-Schule,
insbesondere den Herren Tom Rosenberger und Tobias Stensbeck, deren
Vortrag die Vorlage für diesen Text darstellt und den Korrekturvorschlägen vieler anderer Schüler.