Git

Aus dev.kaibel.net
Zur Navigation springen Zur Suche springen

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:

  1. Dateien bearbeiten
  2. Änderungen prüfen
  3. Änderungen zur Staging Area hinzufügen
  4. Commit erstellen
  5. Ä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:

  1. Branch von main erstellen
  2. Funktion implementieren
  3. Änderungen committen
  4. Branch pushen
  5. Merge Request oder Pull Request erstellen
  6. Code Review durchführen
  7. Branch in main mergen

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

Siehe auch