Git - Fortgeschrittene Techniken und Workflow

Git - Fortgeschrittene Techniken und Workflow
Git ist mit Abstand das beliebteste Versionskontrollsystem der Welt. Die meisten Entwickler kennen die Grundlagen - git add, git commit, git push - aber die wahre Staerke von Git liegt in fortgeschrittenen Techniken, die die Teamproduktivitaet radikal verbessern koennen. In diesem Artikel besprechen wir Branching-Strategien, fortgeschrittene Befehle, Automatisierung mit Hooks, Commit-Konventionen und vieles mehr.
Branching-Strategien#
Die Wahl der richtigen Branching-Strategie ist eine der wichtigsten architektonischen Entscheidungen in einem Projekt. Jede populaere Strategie hat ihre Vor- und Nachteile, und die Wahl sollte von der Teamgroesse, der Deployment-Haeufigkeit und den Projektspezifika abhaengen.
Git Flow#
Git Flow ist eine klassische Strategie, die von Vincent Driessen vorgeschlagen wurde. Sie basiert auf zwei Hauptbranches - main (Produktion) und develop (Entwicklung) - sowie drei Typen von unterstuetzenden Branches.
# Git Flow initialisieren
git flow init
# Neues Feature starten
git flow feature start login-page
# Am Feature arbeiten
git add .
git commit -m "feat: add login form component"
# Feature abschliessen - in develop mergen
git flow feature finish login-page
# Release starten
git flow release start 1.2.0
# Release abschliessen - in main und develop mergen
git flow release finish 1.2.0
# Produktions-Hotfix
git flow hotfix start fix-auth-bug
git flow hotfix finish fix-auth-bug
Vorteile von Git Flow:
- Klare Trennung von Produktions- und Entwicklungscode
- Funktioniert gut mit geplanten Release-Zyklen
- Einfaches Hotfix-Management
Nachteile von Git Flow:
- Komplexitaet - viele Branches zu verwalten
- Lange Integrationszyklen koennen zu Konflikten fuehren
- Nicht geeignet fuer CI/CD mit haeufigen Deployments
Trunk Based Development#
Trunk Based Development (TBD) ist ein Ansatz, bei dem alle Entwickler an einem einzigen Hauptbranch arbeiten. Kurzlebige Feature-Branches (maximal 1-2 Tage) werden schnell zurueck in den Trunk gemergt.
# Kurzlebigen Feature-Branch erstellen
git checkout -b feature/add-search main
# Schnelle Iteration - kleine Commits
git commit -m "feat: add search input component"
git commit -m "feat: add search API integration"
# Haeufiges Rebase auf main
git fetch origin
git rebase origin/main
# Schneller Merge zurueck nach main
git checkout main
git merge feature/add-search
git push origin main
# Feature Flags verwenden, um unfertige Features zu verbergen
# if (featureFlags.isEnabled('new-search')) { ... }
Vorteile von TBD:
- Minimiert Merge-Konflikte
- Ideal fuer CI/CD
- Erzwingt kleine, haeufige Commits
Nachteile von TBD:
- Erfordert ein erfahrenes Team und gute Praktiken
- Notwendigkeit der Verwendung von Feature Flags
- Schwierigere Verwaltung mehrerer Versionen
GitHub Flow#
GitHub Flow ist eine vereinfachte Version, ideal fuer Open-Source-Projekte und Teams, die Continuous Delivery praktizieren.
# Branch von main erstellen
git checkout -b feature/user-dashboard main
# Arbeit und Commits
git add .
git commit -m "feat: add user dashboard layout"
git push -u origin feature/user-dashboard
# Pull Request auf GitHub erstellen
gh pr create --title "Add user dashboard" --body "Implements #42"
# Nach Review und Genehmigung - Merge ueber Weboberflaeche
# oder ueber die Kommandozeile
gh pr merge --squash
Wann welche Strategie waehlen?
| Kriterium | Git Flow | TBD | GitHub Flow | |-----------|----------|-----|-------------| | Teamgroesse | Grosse Teams | Klein-mittel | Klein-mittel | | Release-Zyklus | Geplant | Kontinuierlich | Kontinuierlich | | Komplexitaet | Hoch | Niedrig | Niedrig | | CI/CD | Optional | Erforderlich | Empfohlen |
Interactive Rebase - Geschichte umschreiben#
Interactive Rebase ist eines der maechtigsten Git-Werkzeuge. Es ermoeglicht das Umschreiben der Commit-Geschichte - Zusammenfuegen, Aufteilen, Neuordnen und Bearbeiten von Nachrichten.
# Interaktives Rebase der letzten 5 Commits
git rebase -i HEAD~5
# Rebase auf den main-Branch
git rebase -i main
Im Editor sehen Sie eine Liste von Commits mit verfuegbaren Aktionen:
pick a1b2c3d feat: add user model
pick d4e5f6g fix: typo in user model
pick g7h8i9j feat: add user controller
pick j1k2l3m feat: add user routes
pick m4n5o6p fix: missing import
# Verfuegbare Befehle:
# p, pick = Commit verwenden
# r, reword = Commit verwenden, aber Nachricht bearbeiten
# e, edit = Commit verwenden, aber zum Bearbeiten anhalten
# s, squash = mit vorherigem Commit zusammenfuegen
# f, fixup = wie squash, aber Nachricht verwerfen
# d, drop = Commit entfernen
Typische Anwendungsfaelle:
# Fixes mit dem Haupt-Commit zusammenfuegen (squash)
pick a1b2c3d feat: add user model
fixup d4e5f6g fix: typo in user model
pick g7h8i9j feat: add user controller
pick j1k2l3m feat: add user routes
fixup m4n5o6p fix: missing import
# Commit-Nachricht aendern (reword)
reword a1b2c3d feat: add user model with validation
# Commit in kleinere aufteilen
edit a1b2c3d feat: add user model and controller
# Nach dem Anhalten:
git reset HEAD~1
git add src/models/user.ts
git commit -m "feat: add user model"
git add src/controllers/user.ts
git commit -m "feat: add user controller"
git rebase --continue
Wichtig: Rebasen Sie niemals Commits, die bereits in ein Remote-Repository gepusht und mit anderen Entwicklern geteilt wurden. Das Umschreiben geteilter Geschichte fuehrt zu ernsthaften Problemen.
Cherry-pick - Commits auswaehlen#
Cherry-pick ermoeglicht es, einen einzelnen Commit von einem Branch in einen anderen zu verschieben, ohne den gesamten Branch zu mergen.
# Einzelnen Commit verschieben
git cherry-pick a1b2c3d
# Bereich von Commits verschieben
git cherry-pick a1b2c3d..f6g7h8i
# Cherry-pick ohne automatischen Commit
git cherry-pick --no-commit a1b2c3d
# Konflikte waehrend Cherry-pick loesen
git cherry-pick a1b2c3d
# ... Konflikte loesen ...
git add .
git cherry-pick --continue
# Cherry-pick abbrechen
git cherry-pick --abort
Typische Anwendungsfaelle:
- Hotfixes zwischen Branches verschieben
- Selektives Auswaehlen von Aenderungen aus Feature-Branches
- Backporting von Fixes auf aeltere Versionen
Git Bisect - Binaere Suche nach Bugs#
git bisect hilft, den Commit zu finden, der einen Bug eingefuehrt hat, mittels binaerer Suche. Es ist aeusserst effektiv bei einer langen Commit-Geschichte.
# Bisect-Sitzung starten
git bisect start
# Aktuellen Commit als schlecht markieren
git bisect bad
# Letzten bekannten guten Commit markieren
git bisect good v1.0.0
# Git waehlt einen Commit in der Mitte - testen und markieren
git bisect good # lub git bisect bad
# Fortfahren, bis Git den schuldigen Commit findet
# ...
# Sitzung beenden
git bisect reset
Bisect mit einem Testskript automatisieren:
# Automatischer Bisect mit einem Testbefehl
git bisect start HEAD v1.0.0
git bisect run npm test
# Bisect mit einem eigenen Skript
git bisect run ./scripts/test-regression.sh
# Das Skript sollte 0 (gut) oder 1 (schlecht) zurueckgeben
Git Stash - Temporaere Speicherung von Aenderungen#
Stash ermoeglicht es, uncommitted Aenderungen voruebergehend beiseite zu legen, um zu anderer Arbeit zu wechseln.
# Einfacher Stash
git stash
# Stash mit Beschreibung
git stash push -m "work in progress: login form"
# Stash einschliesslich neuer Dateien (untracked)
git stash push -u -m "WIP: new feature with new files"
# Gestashte Aenderungen auflisten
git stash list
# stash@{0}: On feature/login: work in progress: login form
# stash@{1}: On main: quick experiment
# Letzten Stash wiederherstellen
git stash pop
# Bestimmten Stash wiederherstellen
git stash pop stash@{1}
# Wiederherstellen ohne aus dem Stash zu entfernen
git stash apply stash@{0}
# Aenderungen im Stash anzeigen
git stash show -p stash@{0}
# Branch aus Stash erstellen
git stash branch feature/from-stash stash@{0}
# Stash loeschen
git stash drop stash@{0}
# Alle gestashten Aenderungen loeschen
git stash clear
Git Worktrees - Paralleles Arbeiten an mehreren Branches#
Worktrees ermoeglichen es, mehrere Branches gleichzeitig in verschiedenen Verzeichnissen ausgecheckt zu haben, die sich ein einzelnes .git-Repository teilen.
# Worktree fuer einen bestehenden Branch hinzufuegen
git worktree add ../project-hotfix hotfix/critical-bug
# Worktree mit einem neuen Branch hinzufuegen
git worktree add -b feature/new-ui ../project-new-ui main
# Aktive Worktrees auflisten
git worktree list
# /home/user/project a1b2c3d [main]
# /home/user/project-hotfix d4e5f6g [hotfix/critical-bug]
# /home/user/project-new-ui g7h8i9j [feature/new-ui]
# In einem separaten Worktree arbeiten
cd ../project-hotfix
git add .
git commit -m "fix: critical auth bypass"
git push origin hotfix/critical-bug
# Zum Hauptverzeichnis zurueckkehren
cd ../project
# Worktree entfernen
git worktree remove ../project-hotfix
# Nicht existierende Worktrees aufraeumen
git worktree prune
Vorteile von Worktrees:
- Kein Stashen von Aenderungen beim Kontextwechsel noetig
- Moeglichkeit, verschiedene Branches gleichzeitig zu bauen/testen
- Geteiltes
.git- spart Speicherplatz
Git Submodules - Abhaengigkeitsverwaltung#
Submodules ermoeglichen es, ein Git-Repository in ein anderes als Unterverzeichnis einzubetten.
# Submodul hinzufuegen
git submodule add https://github.com/org/shared-lib.git libs/shared
# Repository mit Submodulen klonen
git clone --recurse-submodules https://github.com/org/main-project.git
# Submodule nach dem Klonen ohne --recurse initialisieren
git submodule init
git submodule update
# Submodul auf die neueste Version aktualisieren
cd libs/shared
git fetch
git checkout v2.0.0
cd ../..
git add libs/shared
git commit -m "chore: update shared-lib to v2.0.0"
# Alle Submodule aktualisieren
git submodule update --remote --merge
# Submodul entfernen
git submodule deinit libs/shared
git rm libs/shared
rm -rf .git/modules/libs/shared
Git Hooks - Prozessautomatisierung#
Hooks sind Skripte, die automatisch als Reaktion auf Git-Ereignisse ausgefuehrt werden. Sie koennen fuer Validierung, Code-Formatierung, Ausfuehren von Tests und viele andere Aufgaben verwendet werden.
Pre-commit Hook#
#!/bin/sh
# .git/hooks/pre-commit
# Code-Formatierung mit Prettier pruefen
echo "Running Prettier check..."
npx prettier --check "src/**/*.{ts,tsx,js,jsx}" || {
echo "FEHLER: Code ist nicht formatiert. Fuehren Sie aus: npx prettier --write ."
exit 1
}
# Linter ausfuehren
echo "Running ESLint..."
npx eslint "src/**/*.{ts,tsx}" --max-warnings 0 || {
echo "FEHLER: ESLint-Fehler. Beheben Sie diese vor dem Commit."
exit 1
}
# TypeScript-Typen pruefen
echo "Running type check..."
npx tsc --noEmit || {
echo "FEHLER: TypeScript-Typfehler."
exit 1
}
echo "All checks passed!"
Commit-msg Hook#
#!/bin/sh
# .git/hooks/commit-msg
commit_msg=$(cat "$1")
# Conventional Commits Format validieren
pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,72}$"
if ! echo "$commit_msg" | head -1 | grep -qE "$pattern"; then
echo "FEHLER: Commit-Nachricht entspricht nicht den Conventional Commits."
echo ""
echo "Format: <Typ>(<Bereich>): <Beschreibung>"
echo ""
echo "Typen: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
echo ""
echo "Beispiele:"
echo " feat(auth): add OAuth2 login flow"
echo " fix(api): handle null response from payment gateway"
echo " docs: update API documentation"
exit 1
fi
Hooks verwalten mit Husky#
Anstatt Hooks manuell in .git/hooks/ zu verwalten, koennen Sie Husky verwenden:
# Husky installieren
npm install -D husky
# Initialisieren
npx husky init
# Pre-commit Hook hinzufuegen
echo "npx lint-staged" > .husky/pre-commit
# lint-staged Konfiguration in package.json
{
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,yml}": ["prettier --write"]
}
}
Conventional Commits und Semantic Versioning#
Conventional Commits ist eine Spezifikation fuer die Struktur von Commit-Nachrichten, die automatische Changelog-Generierung und Versionsverwaltung ermoeglicht.
Conventional Commits Format#
<Typ>[optionaler Bereich]: <Beschreibung>
[optionaler Koerper]
[optionale Fussnote(n)]
Commit-Typen und ihr Einfluss auf die Versionierung:
| Typ | Beschreibung | SemVer |
|-----|------|--------|
| feat | Neues Feature | MINOR (1.x.0) |
| fix | Bugfix | PATCH (1.0.x) |
| docs | Dokumentation | - |
| style | Formatierung | - |
| refactor | Refactoring | - |
| perf | Performance-Optimierung | PATCH |
| test | Tests | - |
| build | Build-System | - |
| ci | CI-Konfiguration | - |
| chore | Sonstiges | - |
Breaking Changes verursachen einen MAJOR-Versionssprung (x.0.0):
feat(api)!: change authentication endpoint response format
BREAKING CHANGE: The /auth/login endpoint now returns
a different JSON structure. See migration guide.
Versionierung automatisieren#
# semantic-release installieren
npm install -D semantic-release @semantic-release/changelog @semantic-release/git
# Konfiguration in .releaserc.json
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/git"
]
}
Monorepo-Strategien#
Monorepo ist ein Ansatz, bei dem mehrere Projekte/Pakete in einem einzigen Repository liegen. Git bietet Werkzeuge, die bei der effizienten Verwaltung solcher Strukturen helfen.
Sparse Checkout#
# Sparse Checkout aktivieren
git sparse-checkout init --cone
# Nur benoetigte Verzeichnisse auswaehlen
git sparse-checkout set packages/frontend packages/shared
# Weiteres Verzeichnis hinzufuegen
git sparse-checkout add packages/backend
# Aktive Verzeichnisse auflisten
git sparse-checkout list
# Sparse Checkout deaktivieren
git sparse-checkout disable
Monorepo-Werkzeuge#
# Turborepo - nur geaenderte Pakete bauen
npx turbo run build --filter=...[HEAD~1]
# Nx - Abhaengigkeitsanalyse
npx nx affected --target=test --base=main
# pnpm Workspaces - Abhaengigkeitsverwaltung
pnpm install --filter @myorg/frontend
Geschichte im Monorepo filtern#
# Logs nur fuer ein bestimmtes Verzeichnis
git log --oneline -- packages/frontend/
# Diff nur fuer ein bestimmtes Paket
git diff main -- packages/api/
# Blame fuer eine Datei in einem Paket
git blame packages/shared/src/utils.ts
Git LFS - Large File Storage#
Git LFS loest das Problem der Speicherung grosser Dateien (Grafiken, 3D-Modelle, Binaerdaten) in Git-Repositories.
# Git LFS installieren
git lfs install
# Grosse Dateien verfolgen
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "assets/videos/**"
# Konfiguration pruefen
cat .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text
# *.zip filter=lfs diff=lfs merge=lfs -text
# .gitattributes zum Repository hinzufuegen
git add .gitattributes
git commit -m "chore: configure Git LFS for binary files"
# Normale Git-Nutzung - LFS arbeitet transparent
git add assets/logo.psd
git commit -m "feat: add new logo design"
git push
# LFS-Status pruefen
git lfs status
git lfs ls-files
Commits signieren (GPG/SSH)#
Das Signieren von Commits ermoeglicht die Verifizierung der Identitaet des Autors und gewaehrleistet die Code-Integritaet.
# GPG-Signierung konfigurieren
gpg --gen-key
gpg --list-secret-keys --keyid-format=long
# Schluessel in Git setzen
git config --global user.signingkey ABC123DEF456
git config --global commit.gpgsign true
# Commit signieren
git commit -S -m "feat: add verified feature"
# Signatur verifizieren
git log --show-signature
# Signierung mit SSH-Schluessel (Git 2.34+)
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
# SSH-Signaturen verifizieren
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
echo "user@example.com ssh-ed25519 AAAA..." >> ~/.ssh/allowed_signers
Die .gitattributes-Datei#
.gitattributes ermoeglicht die Kontrolle darueber, wie Git verschiedene Dateitypen behandelt - von der Zeilenende-Konvertierung bis zu Merge-Strategien.
# Zeilenenden normalisieren
* text=auto
# LF fuer Quelldateien erzwingen
*.js text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.json text eol=lf
*.yml text eol=lf
*.md text eol=lf
# Binaerdateien - keine Konvertierung
*.png binary
*.jpg binary
*.gif binary
*.ico binary
*.woff2 binary
# Eigene Merge-Strategie fuer Lock-Dateien
package-lock.json merge=ours
yarn.lock merge=ours
pnpm-lock.yaml merge=ours
# Binaerdateien vergleichen
*.pdf diff=pdf
# Git LFS
*.psd filter=lfs diff=lfs merge=lfs -text
# Export - aus Archiven ausschliessen
.github/ export-ignore
tests/ export-ignore
.gitignore export-ignore
Fortgeschrittene Merge-Strategien#
Git bietet verschiedene Merge-Strategien, die je nach Situation gewaehlt werden koennen.
# Standardstrategie (ort in neueren Versionen)
git merge feature/new-ui
# Merge mit Beibehaltung der Geschichte (no fast-forward)
git merge --no-ff feature/new-ui
# Ours-Strategie - unsere Version behalten
git merge -s ours legacy-branch
# Merge mit Bevorzugung unserer Aenderungen bei Konflikten
git merge -X ours feature/conflicting
# Merge mit Bevorzugung ihrer Aenderungen bei Konflikten
git merge -X theirs feature/external-update
# Squash-Merge - ein Commit aus dem gesamten Branch
git merge --squash feature/many-commits
git commit -m "feat: add complete user management module"
# Octopus-Merge - mehrere Branches gleichzeitig mergen
git merge feature/a feature/b feature/c
Rerere - Geloeste Konflikte merken#
# Rerere aktivieren (aufgezeichnete Loesung wiederverwenden)
git config --global rerere.enabled true
# Git merkt sich, wie Sie Konflikte geloest haben
# und wird automatisch dieselben Loesungen anwenden
# wenn es in Zukunft auf identische Konflikte trifft
# Gemerkte Loesungen anzeigen
git rerere diff
# Rerere-Cache leeren
git rerere forget <plik>
Konflikte loesen#
Konflikte sind in der Teamarbeit unvermeidlich. Hier sind bewaehrte Ansaetze zu ihrer Loesung.
# Konfliktstatus pruefen
git status
# Konflikte in einer Datei anzeigen
# <<<<<<< HEAD
# unsere Version des Codes
# =======
# ihre Version des Codes
# >>>>>>> feature/other-branch
# Merge-Tool verwenden
git mergetool
# Mit einer bestimmten Version loesen
git checkout --ours -- src/config.ts # unsere Version
git checkout --theirs -- src/config.ts # ihre Version
# Merge abbrechen
git merge --abort
# Rebase abbrechen
git rebase --abort
Best Practices fuer die Konfliktloesung:
- Haeufiges Mergen/Rebasen - je oefter Sie sich mit dem Hauptbranch synchronisieren, desto kleiner die Konflikte
- Kleine Commits - es ist einfacher, Konflikte in kleinen Aenderungen zu verstehen und zu loesen
- Teamkommunikation - informieren Sie, wenn Sie an gemeinsamen Dateien arbeiten
- Visuelle Tools - VS Code, IntelliJ, Beyond Compare erleichtern die Loesung komplexer Konflikte
Nuetzliche Aliase und Konfiguration#
# Nuetzliche Aliase
git config --global alias.lg "log --oneline --graph --all --decorate"
git config --global alias.st "status -sb"
git config --global alias.co "checkout"
git config --global alias.br "branch -vv"
git config --global alias.unstage "reset HEAD --"
git config --global alias.last "log -1 HEAD --stat"
git config --global alias.amend "commit --amend --no-edit"
git config --global alias.wip "commit -am 'WIP: work in progress'"
# Nuetzliche Konfiguration
git config --global pull.rebase true
git config --global push.autoSetupRemote true
git config --global fetch.prune true
git config --global diff.algorithm histogram
git config --global merge.conflictstyle zdiff3
git config --global init.defaultBranch main
git config --global core.autocrlf input
Zusammenfassung#
Fortgeschrittene Git-Techniken koennen die Teamproduktivitaet erheblich verbessern:
- Branching-Strategien - waehlen Sie Git Flow, Trunk Based Development oder GitHub Flow je nach Projektanforderungen
- Interactive Rebase - pflegen Sie eine saubere, lesbare Commit-Geschichte
- Cherry-pick und Bisect - praezises Aenderungsmanagement und Fehlersuche
- Stash und Worktrees - effizienter Kontextwechsel
- Hooks - Automatisierung von Validierung und Qualitaetskontrolle
- Conventional Commits - strukturierte Nachrichten, die Automatisierung ermoeglichen
- Git LFS - Umgang mit grossen Binaerdateien
- Commits signieren - Verifizierung von Identitaet und Code-Integritaet
Der Schluessel liegt darin, diese Techniken schrittweise einzufuehren und an die Spezifika Ihres Projekts anzupassen. Sie muessen nicht alles auf einmal verwenden - beginnen Sie mit dem, was Ihrem Team den groessten Nutzen bringt.
Brauchen Sie Unterstuetzung?#
Bei MDS Software Solutions Group helfen wir bei:
- Gestaltung von Git-Workflows, die auf Ihr Team zugeschnitten sind
- Konfiguration von CI/CD mit fortgeschrittenen Branching-Strategien
- Implementierung von Conventional Commits und automatischer Versionierung
- Migration zu Monorepo und Optimierung grosser Repositories
- Schulungen in fortgeschrittenen Git-Techniken
Kontaktieren Sie uns, um Ihr Projekt zu besprechen!
Team von Programmierexperten, die sich auf moderne Webtechnologien spezialisiert haben.