Git
Git
Git ist ein verteiltes Versionsverwaltungssystem, das zur Verwaltung von Änderungen an Dateien und Quellcode eingesetzt wird. Es ermöglicht, verschiedene Versionen eines Projekts zu speichern, Änderungen nachzuvollziehen, ältere Zustände wiederherzustellen und gemeinsam an Softwareprojekten zu arbeiten.
Git wird besonders häufig in der Softwareentwicklung verwendet, eignet sich aber grundsätzlich für alle textbasierten Dateien, zum Beispiel Konfigurationsdateien, Dokumentationen oder Skripte.
Grundidee
Bei der Entwicklung von Software ändern sich Dateien ständig. Ohne Versionsverwaltung ist es schwierig nachzuvollziehen:
- wann eine Änderung vorgenommen wurde
- wer eine Änderung vorgenommen hat
- warum eine Änderung vorgenommen wurde
- welche Dateien betroffen waren
- wie ein früherer Zustand wiederhergestellt werden kann
Git löst dieses Problem, indem Änderungen in sogenannten Commits gespeichert werden. Jeder Commit beschreibt einen bestimmten Zustand des Projekts.
Verteilte Versionsverwaltung
Git ist ein verteiltes Versionsverwaltungssystem.
Das bedeutet: Jeder Entwickler besitzt eine vollständige Kopie des Repositories einschließlich der gesamten Historie.
Im Gegensatz zu zentralen Systemen wie SVN ist Git nicht dauerhaft auf einen zentralen Server angewiesen.
Vorteile der verteilten Arbeitsweise:
- Arbeiten ohne permanente Internetverbindung
- Lokale Commits ohne Serverzugriff
- Schnelle Operationen
- Hohe Ausfallsicherheit
- Einfache parallele Entwicklung
Ein zentraler Server wird häufig trotzdem verwendet, zum Beispiel über Plattformen wie GitHub, GitLab oder Bitbucket. Dieser Server dient dann vor allem der Zusammenarbeit und Synchronisation.
Repository
Ein Repository ist der Speicherort eines Git-Projekts. Es enthält:
- die Projektdateien
- die Commit-Historie
- Branches
- Tags
- Konfigurationsinformationen
- Metadaten von Git
Ein neues Repository wird mit folgendem Befehl erstellt:
git init
Ein vorhandenes Repository wird mit folgendem Befehl kopiert:
git clone https://example.org/projekt.git
Wichtige Begriffe
| Begriff | Bedeutung |
|---|---|
| Repository | Git-Projekt mit Dateien, Historie und Metadaten |
| Commit | Gespeicherter Zustand des Projekts |
| Branch | Entwicklungszweig innerhalb eines Repositories |
| Merge | Zusammenführen zweier Branches |
| Rebase | Neuaufbau einer Commit-Historie auf Basis eines anderen Branches |
| Remote | Entferntes Repository, zum Beispiel auf GitHub oder GitLab |
| Clone | Lokale Kopie eines entfernten Repositories |
| Pull | Änderungen aus einem entfernten Repository herunterladen und integrieren |
| Push | Lokale Änderungen in ein entferntes Repository hochladen |
| Tag | Markierung eines bestimmten Commits, häufig für Versionen |
Arbeitsbereiche in Git
Git unterscheidet mehrere Arbeitsbereiche.
Working Directory
Das Working Directory enthält die Dateien, an denen aktuell gearbeitet wird.
Wenn eine Datei bearbeitet wird, befindet sich die Änderung zunächst nur im Working Directory.
Staging Area
Die Staging Area ist ein Zwischenspeicher für Änderungen, die in den nächsten Commit aufgenommen werden sollen.
Dateien werden mit folgendem Befehl zur Staging Area hinzugefügt:
git add datei.txt
Alle geänderten Dateien können mit folgendem Befehl hinzugefügt werden:
git add .
Lokales Repository
Das lokale Repository enthält die dauerhaft gespeicherten Commits.
Ein Commit wird mit folgendem Befehl erstellt:
git commit -m "Beschreibung der Änderung"
Typischer Git-Arbeitsablauf
Ein einfacher Arbeitsablauf sieht folgendermaßen aus:
- Dateien bearbeiten
- Änderungen prüfen
- Änderungen zur Staging Area hinzufügen
- Commit erstellen
- Änderungen optional auf einen Server übertragen
Beispiel:
git status git add . git commit -m "Neue Funktion implementiert" git push
Status anzeigen
Der aktuelle Zustand des Repositories wird mit folgendem Befehl angezeigt:
git status
Dieser Befehl zeigt unter anderem:
- geänderte Dateien
- neue Dateien
- gelöschte Dateien
- Dateien in der Staging Area
- den aktuellen Branch
Änderungen anzeigen
Noch nicht vorgemerkte Änderungen können mit folgendem Befehl angezeigt werden:
git diff
Änderungen in der Staging Area können so angezeigt werden:
git diff --staged
Commits
Ein Commit ist eine gespeicherte Momentaufnahme des Projekts.
Ein Commit enthält:
- eine eindeutige ID
- Autorinformationen
- Datum und Uhrzeit
- Commit-Nachricht
- Verweis auf vorherige Commits
- Änderungen am Projektzustand
Beispiel:
git commit -m "Fehler in der Benutzeranmeldung behoben"
Eine gute Commit-Nachricht sollte kurz und verständlich beschreiben, was geändert wurde.
Commit-Historie anzeigen
Die Commit-Historie wird mit folgendem Befehl angezeigt:
git log
Eine kompaktere Darstellung erhält man mit:
git log --oneline
Eine grafische Übersicht über Branches kann so angezeigt werden:
git log --oneline --graph --all
Branches
Ein Branch ist ein Entwicklungszweig.
Branches ermöglichen es, parallel an unterschiedlichen Aufgaben zu arbeiten, ohne den Hauptzweig direkt zu verändern.
Typische Branches sind:
- main
- develop
- feature/login
- bugfix/navigation
- release/1.0
Branch erstellen
Ein neuer Branch wird mit folgendem Befehl erstellt:
git branch feature-login
Zum Wechseln auf den Branch wird verwendet:
git checkout feature-login
In modernen Git-Versionen kann stattdessen auch verwendet werden:
git switch feature-login
Ein Branch kann gleichzeitig erstellt und aktiviert werden:
git switch -c feature-login
Branches anzeigen
Alle lokalen Branches werden mit folgendem Befehl angezeigt:
git branch
Alle lokalen und entfernten Branches werden so angezeigt:
git branch -a
Merge
Ein Merge führt Änderungen aus einem Branch in einen anderen Branch zusammen.
Beispiel:
git switch main git merge feature-login
Dabei werden die Änderungen aus dem Branch feature-login in den Branch main übernommen.
Merge-Konflikte
Ein Merge-Konflikt entsteht, wenn Git Änderungen nicht automatisch zusammenführen kann.
Das passiert zum Beispiel, wenn zwei Branches dieselbe Zeile einer Datei unterschiedlich verändert haben.
Git markiert die betroffenen Stellen in der Datei:
<<<<<<< HEAD Aktuelle Version ======= Andere Version >>>>>>> feature-login
Der Entwickler muss den Konflikt manuell auflösen. Danach wird die Datei erneut hinzugefügt und der Merge abgeschlossen:
git add datei.txt git commit
Rebase
Ein Rebase setzt die Commits eines Branches auf eine neue Basis.
Beispiel:
git switch feature-login git rebase main
Dadurch werden die Commits des Feature-Branches so neu angeordnet, als wären sie direkt auf dem aktuellen Stand von main entstanden.
Unterschied zwischen Merge und Rebase
| Verfahren | Beschreibung | Vorteil | Nachteil |
|---|---|---|---|
| Merge | Führt zwei Branches zusammen und erzeugt bei Bedarf einen Merge-Commit | Historie bleibt vollständig erhalten | Historie kann unübersichtlich werden |
| Rebase | Setzt Commits auf eine neue Basis | Lineare, saubere Historie | Kann problematisch sein, wenn bereits veröffentlichte Commits verändert werden |
Als Faustregel gilt: Rebase sollte nicht unüberlegt auf Branches angewendet werden, die bereits mit anderen Personen geteilt wurden.
Remote Repositories
Ein Remote Repository ist ein entferntes Repository, zum Beispiel auf einem Server.
Typische Plattformen sind:
- GitHub
- GitLab
- Bitbucket
- Gitea
- Forgejo
Die Verbindung zu einem entfernten Repository wird häufig unter dem Namen origin gespeichert.
Remotes anzeigen:
git remote -v
Remote hinzufügen:
git remote add origin https://example.org/projekt.git
Push
Mit push werden lokale Commits in ein entferntes Repository hochgeladen.
git push origin main
Beim ersten Push eines neuen Branches wird häufig verwendet:
git push -u origin feature-login
Die Option -u setzt den entfernten Branch als Standardziel für spätere Push- und Pull-Befehle.
Pull
Mit pull werden Änderungen aus einem entfernten Repository heruntergeladen und in den aktuellen Branch integriert.
git pull
Intern entspricht git pull meistens einer Kombination aus:
git fetch git merge
Je nach Konfiguration kann statt Merge auch Rebase verwendet werden.
Fetch
Mit fetch werden Änderungen aus einem entfernten Repository heruntergeladen, aber noch nicht in den aktuellen Branch integriert.
git fetch
Dadurch kann man zunächst prüfen, welche Änderungen verfügbar sind.
Tags
Ein Tag markiert einen bestimmten Commit.
Tags werden häufig für Softwareversionen verwendet.
Beispiel:
git tag v1.0.0
Ein Tag kann auf den Server übertragen werden mit:
git push origin v1.0.0
Alle Tags anzeigen:
git tag
.gitignore
Die Datei .gitignore legt fest, welche Dateien Git ignorieren soll.
Typische Beispiele:
- temporäre Dateien
- Build-Artefakte
- Logdateien
- lokale Konfigurationsdateien
- Abhängigkeiten wie
node_modules
Beispiel:
node_modules/ *.log .env dist/ build/
Eine .gitignore-Datei verhindert, dass unnötige oder sensible Dateien versehentlich versioniert werden.
Dateien aus Git entfernen
Eine Datei kann aus Git entfernt werden mit:
git rm datei.txt
Soll eine Datei nur aus der Versionsverwaltung entfernt werden, aber lokal erhalten bleiben, verwendet man:
git rm --cached datei.txt
Das ist besonders nützlich, wenn eine Datei versehentlich versioniert wurde und anschließend in .gitignore eingetragen wird.
Änderungen rückgängig machen
Git bietet verschiedene Möglichkeiten, Änderungen rückgängig zu machen.
Nicht gespeicherte Änderung verwerfen
git restore datei.txt
Datei aus der Staging Area entfernen
git restore --staged datei.txt
Letzten Commit ändern
git commit --amend
Dieser Befehl verändert den letzten Commit. Er sollte vorsichtig verwendet werden, wenn der Commit bereits veröffentlicht wurde.
Commit rückgängig machen
Ein veröffentlichter Commit sollte meistens mit git revert rückgängig gemacht werden:
git revert COMMIT_ID
Dabei entsteht ein neuer Commit, der die Änderungen des alten Commits rückgängig macht.
Reset
Mit git reset kann der aktuelle Branch auf einen früheren Zustand zurückgesetzt werden.
Beispiel:
git reset --soft HEAD~1
Dieser Befehl entfernt den letzten Commit, behält die Änderungen aber in der Staging Area.
git reset --mixed HEAD~1
Dieser Befehl entfernt den letzten Commit und nimmt die Änderungen aus der Staging Area heraus.
git reset --hard HEAD~1
Dieser Befehl entfernt den letzten Commit und verwirft die Änderungen vollständig.
Achtung: git reset --hard kann nicht gespeicherte Arbeit dauerhaft löschen.
Stash
Mit stash können aktuelle Änderungen vorübergehend gespeichert werden, ohne direkt einen Commit zu erstellen.
Änderungen speichern:
git stash
Gespeicherte Änderungen anzeigen:
git stash list
Letzten Stash wiederherstellen:
git stash pop
Stash wiederherstellen, aber nicht löschen:
git stash apply
Git-Konfiguration
Vor der Nutzung von Git sollten Name und E-Mail-Adresse eingerichtet werden:
git config --global user.name "Max Mustermann" git config --global user.email "max@example.org"
Aktuelle Konfiguration anzeigen:
git config --list
Git-Objektmodell
Git speichert Inhalte intern als Objekte.
Wichtige Objekttypen sind:
| Objekttyp | Bedeutung |
|---|---|
| Blob | Inhalt einer Datei |
| Tree | Verzeichnisstruktur |
| Commit | Projektzustand mit Metadaten und Verweisen |
| Tag | Markierung eines bestimmten Objekts |
Git speichert nicht einfach nur Unterschiede zwischen Dateien, sondern verwaltet Projektzustände über ein internes Objektmodell. Zur Speicheroptimierung kann Git Objekte später komprimieren und effizient ablegen.
Hashes
Git identifiziert Objekte über Hashwerte.
Ein Commit besitzt beispielsweise eine eindeutige Commit-ID:
a3f5c9d7e1b2...
Diese ID wird aus dem Inhalt und den Metadaten erzeugt. Ändert sich der Inhalt, ändert sich auch der Hash.
Historisch verwendet Git SHA-1. Neuere Git-Versionen unterstützen auch SHA-256-Repositories.
HEAD
HEAD bezeichnet in Git den aktuell ausgecheckten Commit.
Meist zeigt HEAD auf den aktuellen Branch.
Beispiel:
HEAD -> main
Wenn HEAD direkt auf einen Commit zeigt und nicht auf einen Branch, spricht man von einem detached HEAD.
Detached HEAD
Ein detached HEAD entsteht, wenn ein bestimmter Commit direkt ausgecheckt wird:
git checkout COMMIT_ID
In diesem Zustand befindet man sich nicht auf einem Branch. Neue Commits können dadurch leicht verloren gehen, wenn kein neuer Branch erstellt wird.
Sicherer ist:
git switch -c test-branch COMMIT_ID
Submodule
Ein Submodule ermöglicht es, ein anderes Git-Repository innerhalb eines Repositories einzubinden.
Beispiel:
git submodule add https://example.org/bibliothek.git libs/bibliothek
Submodule werden häufig verwendet, wenn externe Bibliotheken oder gemeinsam genutzte Komponenten eingebunden werden sollen.
Nachteile von Submodulen:
- zusätzliche Komplexität
- getrennte Historien
- Fehleranfälligkeit bei Updates
- schwieriger für Einsteiger
Git Hooks
Git Hooks sind Skripte, die bei bestimmten Git-Ereignissen automatisch ausgeführt werden.
Beispiele:
- vor einem Commit
- nach einem Commit
- vor einem Push
- nach einem Merge
Typische Einsatzzwecke:
- Codeformatierung prüfen
- Tests ausführen
- Commit-Nachrichten validieren
- Sicherheitsprüfungen durchführen
Hooks befinden sich im Verzeichnis:
.git/hooks/
Typische Workflows
Feature-Branch-Workflow
Beim Feature-Branch-Workflow wird für jede neue Funktion ein eigener Branch erstellt.
Ablauf:
- Branch von
mainerstellen - Funktion implementieren
- Änderungen committen
- Branch pushen
- Merge Request oder Pull Request erstellen
- Code Review durchführen
- Branch in
mainmergen
Dieser Workflow ist in vielen Teams Standard.
Gitflow
Gitflow verwendet mehrere feste Branch-Typen:
- main
- develop
- feature/*
- release/*
- hotfix/*
Gitflow eignet sich besonders für Projekte mit klaren Release-Zyklen.
Für kleinere Projekte kann Gitflow jedoch unnötig komplex sein.
Trunk-Based Development
Beim Trunk-Based Development arbeiten Entwickler möglichst direkt auf einem Hauptbranch oder verwenden nur sehr kurzlebige Branches.
Vorteile:
- schnelle Integration
- weniger Merge-Konflikte
- gut geeignet für Continuous Integration
Nachteile:
- erfordert gute Tests
- erfordert disziplinierte Entwicklung
- unfertige Funktionen müssen oft über Feature Flags abgesichert werden
Git und Plattformen
Git selbst ist ein Kommandozeilenwerkzeug und Versionsverwaltungssystem.
Plattformen wie GitHub oder GitLab sind zusätzliche Dienste, die Git-Repositories hosten und weitere Funktionen bereitstellen.
Typische Zusatzfunktionen solcher Plattformen:
- Pull Requests oder Merge Requests
- Issue-Tracking
- Projektmanagement
- Continuous Integration
- Code Reviews
- Wiki-Funktionen
- Rechteverwaltung
Git und GitHub sind daher nicht dasselbe. Git ist das Versionsverwaltungssystem, GitHub ist eine Plattform zur Zusammenarbeit mit Git.
Häufige Befehle
| Befehl | Bedeutung |
|---|---|
git init
|
Neues Repository erstellen |
git clone
|
Repository kopieren |
git status
|
Aktuellen Zustand anzeigen |
git add
|
Änderungen zur Staging Area hinzufügen |
git commit
|
Änderungen speichern |
git log
|
Commit-Historie anzeigen |
git branch
|
Branches anzeigen oder erstellen |
git switch
|
Branch wechseln |
git merge
|
Branches zusammenführen |
git rebase
|
Commits auf neue Basis setzen |
git fetch
|
Änderungen vom Remote herunterladen |
git pull
|
Änderungen herunterladen und integrieren |
git push
|
Änderungen hochladen |
git stash
|
Änderungen vorübergehend speichern |
git tag
|
Version markieren |
Best Practices
Kleine Commits erstellen
Commits sollten möglichst kleine, logisch zusammenhängende Änderungen enthalten.
Schlecht:
git commit -m "Alles geändert"
Besser:
git commit -m "Validierung für Login-Formular ergänzt"
Aussagekräftige Commit-Nachrichten verwenden
Eine gute Commit-Nachricht beschreibt, was geändert wurde und idealerweise warum.
Beispiele:
- Fehler beim Speichern leerer Formulare behoben
- Benutzerrolle zur Rechteprüfung hinzugefügt
- Datenbankmigration für Produkte erstellt
Branches sinnvoll benennen
Gute Branchnamen sind kurz und beschreibend.
Beispiele:
- feature/login
- bugfix/navbar
- hotfix/payment-error
- docs/git-grundlagen
Regelmäßig synchronisieren
In Teamprojekten sollte regelmäßig mit dem entfernten Repository synchronisiert werden:
git fetch git pull
Dadurch werden Konflikte frühzeitig erkannt.
Keine sensiblen Daten committen
Nicht in ein Repository gehören:
- Passwörter
- API-Schlüssel
- private Zertifikate
- Datenbankzugänge
- persönliche Zugangsdaten
Solche Dateien sollten über .gitignore ausgeschlossen werden.
Typische Fehler
Zu große Commits
Sehr große Commits sind schwer zu prüfen und schwer rückgängig zu machen.
Unklare Commit-Nachrichten
Nachrichten wie „Update“, „Fix“ oder „Änderungen“ sind wenig hilfreich.
Direktes Arbeiten auf main
In Teamprojekten sollte nicht immer direkt auf dem Hauptbranch gearbeitet werden.
Feature-Branches erhöhen Übersichtlichkeit und Sicherheit.
Secrets im Repository
Ein einmal veröffentlichter API-Schlüssel sollte als kompromittiert betrachtet und ersetzt werden.
Das Entfernen aus späteren Commits reicht nicht aus, da der Schlüssel weiterhin in der Historie vorhanden sein kann.
Vorteile von Git
- sehr schnell bei lokalen Operationen
- verteilte Arbeitsweise
- starke Unterstützung für Branches
- gute Nachvollziehbarkeit von Änderungen
- große Verbreitung
- Integration in viele Entwicklungsumgebungen
- geeignet für kleine und große Projekte
Nachteile von Git
- für Einsteiger teilweise komplex
- viele Befehle besitzen unterschiedliche Modi
- Merge-Konflikte können schwierig sein
- falsche Nutzung von Reset oder Rebase kann Arbeit zerstören
- Binärdateien werden weniger effizient verwaltet als Textdateien
Git in der Softwareentwicklung
In modernen Softwareprojekten ist Git häufig eng mit weiteren Entwicklungsprozessen verbunden.
Dazu gehören:
- Code Reviews
- Continuous Integration
- automatisierte Tests
- Deployment-Pipelines
- Release-Management
- Issue-Tracking
- Dokumentation
Git bildet damit nicht nur die technische Grundlage für Versionsverwaltung, sondern auch einen wichtigen Bestandteil professioneller Entwicklungsprozesse.
Beispiel: Einfaches Projekt mit Git verwalten
Ein neues Projekt wird erstellt:
mkdir mein-projekt cd mein-projekt git init
Eine Datei wird angelegt:
echo "# Mein Projekt" > README.md
Die Datei wird versioniert:
git add README.md git commit -m "README erstellt"
Ein Remote wird hinzugefügt:
git remote add origin https://example.org/mein-projekt.git git push -u origin main
Beispiel: Arbeiten mit Feature-Branch
Neuen Branch erstellen:
git switch -c feature-benutzerprofil
Änderungen durchführen und committen:
git add . git commit -m "Benutzerprofil ergänzt"
Branch hochladen:
git push -u origin feature-benutzerprofil
Danach kann auf einer Plattform wie GitHub oder GitLab ein Pull Request beziehungsweise Merge Request erstellt werden.
Abgrenzung zu anderen Systemen
| System | Typ | Besonderheit |
|---|---|---|
| Git | Verteilte Versionsverwaltung | Sehr schnelle Branches und lokale Historie |
| SVN | Zentrale Versionsverwaltung | Einfacheres zentrales Modell |
| Mercurial | Verteilte Versionsverwaltung | Ähnlich wie Git, aber weniger verbreitet |
| CVS | Zentrale Versionsverwaltung | Älteres System |
Zusammenfassung
Git ist ein leistungsfähiges und weit verbreitetes Versionsverwaltungssystem. Es ermöglicht Entwicklern, Änderungen zuverlässig zu speichern, parallele Entwicklungszweige zu verwalten und gemeinsam an Softwareprojekten zu arbeiten.
Die wichtigsten Konzepte sind:
- Repository
- Commit
- Branch
- Merge
- Rebase
- Remote
- Push und Pull
- Staging Area
Durch seine verteilte Architektur, hohe Geschwindigkeit und starke Branch-Unterstützung ist Git heute ein Standardwerkzeug der professionellen Softwareentwicklung.
Literatur und Weblinks
- Offizielle Git-Webseite: https://git-scm.com/
- Pro Git Book: https://git-scm.com/book/de/v2
- Git-Dokumentation: https://git-scm.com/docs
- GitHub Docs: https://docs.github.com/
- GitLab Docs: https://docs.gitlab.com/