Git-Workflow-Muster
Best Practices für die Git-Versionskontrolle, Branching-Strategien und kollaborative Entwicklung.
Wann aktivieren
- Einrichten eines Git-Workflows für ein neues Projekt
- Entscheidung über eine Branching-Strategie (GitFlow, trunk-based, GitHub flow)
- Schreiben von Commit-Nachrichten und PR-Beschreibungen
- Beheben von Merge-Konflikten
- Verwalten von Releases und Versions-Tags
- Einarbeitung neuer Teammitglieder in Git-Praktiken
Branching-Strategien
GitHub Flow (Einfach, für die meisten empfohlen)
Am besten geeignet für kontinuierliche Bereitstellung und kleine bis mittelgroße Teams.
main (geschützt, immer bereitstellbar)
│
├── feature/user-auth → PR → merge zu main
├── feature/payment-flow → PR → merge zu main
└── fix/login-bug → PR → merge zu main
Regeln:
mainist immer bereitstellbar- Feature-Branches von
mainaus erstellen - Pull Request öffnen, wenn er zur Überprüfung bereit ist
- Nach Genehmigung und bestandenem CI in
mainmergen - Sofort nach dem Merge bereitstellen
Trunk-basierte Entwicklung (Hochgeschwindigkeitsteams)
Am besten geeignet für Teams mit starkem CI/CD und Feature-Flags.
main (trunk)
│
├── kurzlebiger Feature-Branch (max. 1-2 Tage)
├── kurzlebiger Feature-Branch
└── kurzlebiger Feature-Branch
Regeln:
- Jeder committed in
mainoder in sehr kurzlebigen Branches - Feature-Flags verbergen unvollständige Arbeit
- CI muss vor dem Merge bestanden werden
- Mehrmals täglich bereitstellen
GitFlow (Komplex, releasezyklusgesteuert)
Am besten geeignet für geplante Releases und Unternehmensprojekte.
main (Produktions-Releases)
│
└── develop (Integrationsbranch)
│
├── feature/user-auth
├── feature/payment
│
├── release/1.0.0 → merge zu main und develop
│
└── hotfix/critical → merge zu main und develop
Regeln:
mainenthält nur produktionsbereiten Codedevelopist der Integrationsbranch- Feature-Branches von
develop, zurück zudevelopmergen - Release-Branches von
develop, zumainunddevelopmergen - Hotfix-Branches von
main, zumainunddevelopmergen
Wann welche verwenden
| Strategie | Teamgröße | Release-Rhythmus | Am besten geeignet für |
|---|---|---|---|
| GitHub Flow | Beliebig | Kontinuierlich | SaaS, Web-Apps, Startups |
| Trunk-basiert | 5+ erfahren | Mehrmals/Tag | Hochgeschwindigkeitsteams, Feature-Flags |
| GitFlow | 10+ | Geplant | Unternehmen, regulierte Branchen |
Commit-Nachrichten
Konventionelles Commits-Format
<typ>(<umfang>): <betreff>
[optionaler Textkörper]
[optionaler Fuß]
Typen
| Typ | Verwendung | Beispiel |
|---|---|---|
feat | Neue Funktion | feat(auth): OAuth2-Login hinzufügen |
fix | Fehlerbehebung | fix(api): Null-Antwort im Benutzerendpunkt behandeln |
docs | Dokumentation | docs(readme): Installationsanleitung aktualisieren |
style | Formatierung, keine Codeänderung | style: Einrückung in Login-Komponente korrigieren |
refactor | Code-Umstrukturierung | refactor(db): Verbindungspool in Modul auslagern |
test | Hinzufügen/Aktualisieren von Tests | test(auth): Unit-Tests für Token-Validierung hinzufügen |
chore | Wartungsaufgaben | chore(deps): Abhängigkeiten aktualisieren |
perf | Leistungsverbesserung | perf(query): Index zur Benutzertabelle hinzufügen |
ci | CI/CD-Änderungen | ci: PostgreSQL-Service zum Test-Workflow hinzufügen |
revert | Vorherigen Commit rückgängig machen | revert: revert "feat(auth): OAuth2-Login hinzufügen" |
Gute vs. schlechte Beispiele
# SCHLECHT: Vage, kein Kontext
git commit -m "Sachen gefixt"
git commit -m "Updates"
git commit -m "WIP"
# GUT: Klar, spezifisch, erklärt das Warum
git commit -m "fix(api): Anfragen bei 503 Service Unavailable wiederholen
Die externe API gibt während Stoßzeiten gelegentlich 503-Fehler zurück.
Exponentielle Backoff-Wiederholungslogik mit max. 3 Versuchen hinzugefügt.
Schließt #123"
Commit-Nachrichten-Vorlage
Erstelle .gitmessage im Repository-Stammverzeichnis:
# <typ>(<umfang>): <betreff>
# # Typen: feat, fix, docs, style, refactor, test, chore, perf, ci, revert
# Umfang: api, ui, db, auth, etc.
# Betreff: Imperativ, kein Punkt, max. 50 Zeichen
#
# [optionaler Textkörper] - Warum erklären, nicht Was
# [optionaler Fuß] - Breaking changes, schließt #issue
Aktivieren mit: git config commit.template .gitmessage
Merge vs. Rebase
Merge (bewahrt Historie)
# Erstellt einen Merge-Commit
git checkout main
git merge feature/user-auth
# Ergebnis:
# * Merge-Commit
# |\
# | * Feature-Commits
# |/
# * Main-Commits
Verwenden, wenn:
- Feature-Branches in
maingemergt werden - Die genaue Historie erhalten bleiben soll
- Mehrere Personen am Branch gearbeitet haben
- Der Branch bereits gepusht wurde und andere darauf basiert haben könnten
Rebase (lineare Historie)
# Schreibt Feature-Commits auf den Ziel-Branch um
git checkout feature/user-auth
git rebase main
# Ergebnis:
# * Feature-Commits (umschrieben)
# * Main-Commits
Verwenden, wenn:
- Der lokale Feature-Branch mit dem neuesten
mainaktualisiert wird - Eine lineare, saubere Historie gewünscht wird
- Der Branch nur lokal ist (nicht gepusht)
- Man allein an diesem Branch arbeitet
Rebase-Workflow
# Feature-Branch mit neuestem main aktualisieren (vor PR)
git checkout feature/user-auth
git fetch origin
git rebase origin/main
# Eventuelle Konflikte beheben
# Tests sollten weiterhin bestehen
# Force-Push (nur, wenn man der einzige Mitwirkende ist)
git push --force-with-lease origin feature/user-auth
Wann NICHT rebasen
# NIEMALS Branches rebasen, die:
- In ein gemeinsames Repository gepusht wurden
- Andere als Basis für ihre Arbeit verwendet haben
- Geschützte Branches sind (main, develop)
- Bereits gemergt wurden
# Grund: Rebase schreibt Historie um und zerstört die Arbeit anderer
Pull-Request-Workflow
PR-Titelformat
<typ>(<umfang>): <beschreibung>
Beispiele:
feat(auth): SSO-Unterstützung für Enterprise-Benutzer hinzufügen
fix(api): Race-Condition in der Auftragsverarbeitung beheben
docs(api): OpenAPI-Spezifikation für v2-Endpunkte hinzufügen
PR-Beschreibungsvorlage
## Was
Kurze Beschreibung, was dieser PR tut.
## Warum
Motivation und Kontext erklären.
## Wie
Wichtige Implementierungsdetails, die hervorzuheben sind.
## Testen
- [ ] Unit-Tests hinzugefügt/aktualisiert
- [ ] Integrationstests hinzugefügt/aktualisiert
- [ ] Manuelles Testen durchgeführt
## Screenshots (falls zutreffend)
Vorher-/Nachher-Screenshots für UI-Änderungen.
## Checkliste
- [ ] Code folgt den Projekt-Stilrichtlinien
- [ ] Selbstüberprüfung abgeschlossen
- [ ] Kommentare für komplexe Logik hinzugefügt
- [ ] Dokumentation aktualisiert
- [ ] Keine neuen Warnungen eingeführt
- [ ] Tests bestehen lokal
- [ ] Verknüpfte Issues verlinkt
Schließt #123
Code-Review-Checkliste
Für Prüfer:
- Löst der Code das genannte Problem?
- Werden alle Randfälle behandelt?
- Ist der Code lesbar und wartbar?
- Gibt es ausreichende Tests?
- Gibt es Sicherheitsbedenken?
- Ist die Commit-Historie sauber (ggf. squasht)?
Für Autoren:
- Selbstüberprüfung vor der Anfrage zur Überprüfung abgeschlossen
- CI bestanden (Tests, Lint, Typecheck)
- PR-Größe angemessen (ideal <500 Zeilen)
- Bezieht sich auf eine einzelne Funktion/Korrektur
- Beschreibung erklärt die Änderung klar
Konfliktlösung
Konflikte identifizieren
# Vor dem Merge auf Konflikte prüfen
git checkout main
git merge feature/user-auth --no-commit --no-ff
# Bei Konflikten zeigt Git:
# CONFLICT (content): Merge conflict in src/auth/login.ts
# Automatischer Merge fehlgeschlagen; Konflikte beheben und Ergebnis committen.
Konflikte beheben
# Konfliktdateien anzeigen
git status
# Konfliktmarkierungen in der Datei anzeigen
# <<<<<<< HEAD
# Inhalt von main
# =======
# Inhalt vom Feature-Branch
# >>>>>>> feature/user-auth
# Option 1: Manuelle Lösung
# Datei bearbeiten, Markierungen entfernen, korrekten Inhalt behalten
# Option 2: Merge-Tool verwenden
git mergetool
# Option 3: Eine Seite übernehmen
git checkout --ours src/auth/login.ts # main-Version behalten
git checkout --theirs src/auth/login.ts # Feature-Version behalten
# Nach der Lösung, stagen und committen
git add src/auth/login.ts
git commit
Strategien zur Konfliktvermeidung
# 1. Feature-Branches klein und kurzlebig halten
# 2. Häufig auf main rebasen
git checkout feature/user-auth
git fetch origin
git rebase origin/main
# 3. Mit dem Team über gemeinsam genutzte Dateien kommunizieren
# 4. Feature-Flags statt langlebiger Branches verwenden
# 5. PRs zeitnah überprüfen und mergen
Branch-Verwaltung
Namenskonventionen
# Feature-Branches
feature/user-authentication
feature/JIRA-123-payment-integration
# Fehlerbehebungen
fix/login-redirect-loop
fix/456-null-pointer-exception
# Hotfixes (Produktionsprobleme)
hotfix/critical-security-patch
hotfix/database-connection-leak
# Releases
release/1.2.0
release/2024-01-hotfix
# Experimente/PoCs
experiment/new-caching-strategy
poc/graphql-migration
Branch-Bereinigung
# Lokale gemergte Branches löschen
git branch --merged main | grep -v "^\*\|main" | xargs -n 1 git branch -d
# Remote-Tracking-Referenzen für gelöschte Remote-Branches aktualisieren
git fetch -p
# Lokalen Branch löschen
git branch -d feature/user-auth # Sicher löschen (nur wenn gemergt)
git branch -D feature/user-auth # Löschen erzwingen
# Remote-Branch löschen
git push origin --delete feature/user-auth
Stash-Workflow
# Arbeit in Arbeit sichern
git stash push -m "WIP: Benutzerauthentifizierung"
# Stashes auflisten
git stash list
# Neuesten Stash anwenden
git stash pop
# Bestimmten Stash anwenden
git stash apply stash@{2}
# Stash löschen
git stash drop stash@{0}
Release-Verwaltung
Semantische Versionierung
MAJOR.MINOR.PATCH
MAJOR: Bahnbrechende Änderungen
MINOR: Neue Funktionen, abwärtskompatibel
PATCH: Fehlerbehebungen, abwärtskompatibel
Beispiele:
1.0.0 → 1.0.1 (patch: Fehlerbehebung)
1.0.1 → 1.1.0 (minor: neue Funktion)
1.1.0 → 2.0.0 (major: bahnbrechende Änderung)
Releases erstellen
# Annotierten Tag erstellen
git tag -a v1.2.0 -m "Release v1.2.0
Funktionen:
- Benutzerauthentifizierung hinzugefügt
- Passwort-Reset implementiert
Behebungen:
- Login-Weiterleitungsproblem behoben
Bahbrechende Änderungen:
- Keine"
# Tag zu Remote pushen
git push origin v1.2.0
# Tags auflisten
git tag -l
# Tag löschen
git tag -d v1.2.0
git push origin --delete v1.2.0
Changelog-Erstellung
# Changelog aus Commits generieren
git log v1.1.0..v1.2.0 --oneline --no-merges
# Oder conventional-changelog verwenden
npx conventional-changelog -i CHANGELOG.md -s
Git-Konfiguration
Wesentliche Konfigurationen
# Benutzeridentität
git config --global user.name "Ihr Name"
git config --global user.email "[email protected]"
# Standard-Branchname
git config --global init.defaultBranch main
# Pull-Verhalten (Rebase statt Merge)
git config --global pull.rebase true
# Push-Verhalten (nur aktuellen Branch pushen)
git config --global push.default current
# Tippfehler automatisch korrigieren
git config --global help.autocorrect 1
# Besseren Diff-Algorithmus verwenden
git config --global diff.algorithm histogram
# Farbausgabe
git config --global color.ui auto
Nützliche Aliase
# In ~/.gitconfig hinzufügen
[alias]
co = checkout
br = branch
ci = commit
st = status
unstage = reset HEAD --
last = log -1 HEAD
visual = log --oneline --graph --all
amend = commit --amend --no-edit
wip = commit -m "WIP"
undo = reset --soft HEAD~1
contributors = shortlog -sn
Gitignore-Muster
# Abhängigkeiten
node_modules/
vendor/
# Build-Ausgaben
dist/
build/
*.o
*.exe
# Umgebungsdateien
.env
.env.local
.env.*.local
# IDE
.idea/
.vscode/
*.swp
*.swo
# Betriebssystemdateien
.DS_Store
Thumbs.db
# Logs
*.log
logs/
# Testabdeckung
coverage/
# Cache
.cache/
*.tsbuildinfo
Häufige Workflows
Eine neue Funktion starten
# 1. Main-Branch aktualisieren
git checkout main
git pull origin main
# 2. Feature-Branch erstellen
git checkout -b feature/user-auth
# 3. Änderungen vornehmen und committen
git add .
git commit -m "feat(auth): OAuth2-Login implementieren"
# 4. Zu Remote pushen
git push -u origin feature/user-auth
# 5. Pull Request auf GitHub/GitLab erstellen
Einen PR mit neuen Änderungen aktualisieren
# 1. Weitere Änderungen vornehmen
git add .
git commit -m "feat(auth): Fehlerbehandlung hinzufügen"
# 2. Updates pushen
git push origin feature/user-auth
Fork mit Upstream synchronisieren
# 1. Upstream-Remote hinzufügen (einmalig)
git remote add upstream https://github.com/original/repo.git
# 2. Upstream abrufen
git fetch upstream
# 3. upstream/main in eigenen main mergen
git checkout main
git merge upstream/main
# 4. In den eigenen Fork pushen
git push origin main
Fehler rückgängig machen
# Letzten Commit rückgängig machen (Änderungen behalten)
git reset --soft HEAD~1
# Letzten Commit rückgängig machen (Änderungen verwerfen)
git reset --hard HEAD~1
# Letzten, bereits gepushten Commit rückgängig machen
git revert HEAD
git push origin main
# Bestimmte Dateiänderungen rückgängig machen
git checkout HEAD -- pfad/zur/datei
# Letzte Commit-Nachricht korrigieren
git commit --amend -m "Neue Nachricht"
# Vergessene Datei zum letzten Commit hinzufügen
git add vergessene-datei
git commit --amend --no-edit
Git-Hooks
Pre-Commit-Hook
#!/bin/bash
# .git/hooks/pre-commit
# Linting ausführen
npm run lint || exit 1
# Tests ausführen
npm test || exit 1
# Auf Secrets prüfen
if git diff --cached | grep -E '(password|api_key|secret)'; then
echo "Mögliches Secret erkannt. Commit abgebrochen."
exit 1
fi
Pre-Push-Hook
#!/bin/bash
# .git/hooks/pre-push
# Vollständige Testsuite ausführen
npm run test:all || exit 1
# Auf console.log-Anweisungen prüfen
if git diff origin/main | grep -E 'console\.log'; then
echo "Bitte console.log-Anweisungen vor dem Push entfernen."
exit 1
fi
Anti-Patterns
# SCHLECHT: Direktes Committen in main
git checkout main
git commit -m "Bug beheben"
# GUT: Feature-Branches und PRs verwenden
# SCHLECHT: Secrets committen
git add .env # Enthält API-Schlüssel
# GUT: In .gitignore aufnehmen, Umgebungsvariablen verwenden
# SCHLECHT: Riesige PRs (1000+ Zeilen)
# GUT: In kleinere, fokussierte PRs aufteilen
# SCHLECHT: "Update"-Commit-Nachrichten
git commit -m "update"
git commit -m "fix"
# GUT: Beschreibende Nachrichten
git commit -m "fix(auth): Weiterleitungsschleife nach Login beheben"
# SCHLECHT: Öffentliche Historie umschreiben
git push --force origin main
# GUT: Für öffentliche Branches revert verwenden
git revert HEAD
# SCHLECHT: Langlebige Feature-Branches (Wochen/Monate)
# GUT: Branches kurz halten (Tage), häufig rebasen
# SCHLECHT: Feature-Branch ohne Tests oder CI
git push origin feature/user-auth
# GUT: Tests schreiben und CI vor dem Push bestehen