Developer Tools

Git Workflow Guide: Branching, Merging und Teamkollaboration

Meistere Git-Branching-Strategien, Best Practices für Commits, Rebasing vs. Merging und die Workflows professioneller Entwicklungsteams.

8 Min. Lesezeit

Entwickler schaut auf Code auf einem Bildschirm

Git ist das Fundament des Workflows jedes modernen Software-Teams. Dennoch verwenden viele Entwickler nur commit, push und pull – und lassen dabei die Features ungenutzt, die kollaborative Entwicklung reibungslos und konfliktfrei machen. Dieser Leitfaden behandelt Branching-Strategien, Commit-Praktiken und die täglich genutzten Befehle professioneller Teams.

Das grundlegende Denkmodell

Git ist ein gerichteter azyklischer Graph aus Snapshots (Commits). Jeder Commit zeigt auf seinen oder seine Vorgänger. Branches sind lediglich benannte Zeiger auf Commits – leichtgewichtig und schnell erstellt.

main:    A → B → C → D
feature:         C → E → F

Branching kopiert keine Dateien – es wird lediglich ein neuer Zeiger erstellt. Deshalb dauert das Erstellen eines Branches nur Millisekunden, unabhängig von der Repository-Größe.

Branching-Strategien

GitHub Flow (einfach, Continuous Delivery)

Ideal für Teams, die häufig deployen:

  1. main ist jederzeit deploybar
  2. Für jede Änderung einen Feature-Branch erstellen
  3. Pull Request öffnen, wenn der Code bereit für das Review ist
  4. Nach Genehmigung in main mergen
  5. Sofort deployen
git checkout -b feature/add-user-auth
# ... Änderungen vornehmen ...
git push origin feature/add-user-auth
# PR öffnen → Review → Merge → Deploy

Git Flow (strukturierte Releases)

Ideal für Produkte mit versionierten Releases (Apps, Libraries):

  • main — nur Produktionscode
  • develop — Integrations-Branch
  • feature/* — neue Features (Branch von develop)
  • release/* — Release-Vorbereitung (Branch von develop)
  • hotfix/* — dringende Produktionskorrekturen (Branch von main)

Stärker strukturiert, aber mit mehr Aufwand verbunden. Verwende GitHub Flow, es sei denn, du hast einen echten Bedarf an parallelem Release-Management.

Trunk-Based Development

Entwickler committen direkt in main (oder kurzlebige Branches < 1 Tag). Feature-Flags steuern, was Nutzer sehen. Erfordert eine starke CI/CD-Pipeline und Testabdeckung. Wird von Google, Facebook und Teams mit hoher Entwicklungsgeschwindigkeit eingesetzt.

Gute Commit-Messages schreiben

Die Commit-Message ist ein Brief an dein zukünftiges Ich (und deine Teamkollegen). Folge dem Conventional Commits-Format:

<type>(<scope>): <kurze Zusammenfassung>

<optionaler Textkörper — Was und Warum, nicht Wie>

<optionaler Footer — Breaking Changes, Issue-Referenzen>

Typen:

  • feat — neues Feature
  • fix — Bugfix
  • docs — nur Dokumentation
  • refactor — Code-Änderung, die weder einen Bug behebt noch ein Feature hinzufügt
  • test — Tests hinzufügen oder korrigieren
  • chore — Build-Prozess, Abhängigkeiten, Tooling

Beispiele:

feat(auth): add JWT refresh token rotation

Implements sliding session windows using refresh token rotation.
Previous tokens are invalidated on use to detect theft.

Closes #142
fix(api): return 404 instead of 500 for missing user

The /users/:id endpoint was throwing an unhandled exception when
the user didn't exist. Now returns a proper 404 with error message.

Faustregel: Wenn deine Commit-Message fix stuff oder WIP lautet, hasst dich dein Team dafür. Sei aussagekräftig.

Merge vs. Rebase

Merge

git checkout main
git merge feature/my-feature

Erstellt einen Merge-Commit, der zwei Branches zusammenführt. Die vollständige Historie bleibt erhalten – du kannst genau sehen, wann Branches abgewichen und wieder zusammengeführt wurden.

A → B → C → M (Merge-Commit)
         ↑   ↑
         E → F (feature)

Merge verwenden für: das Integrieren langlebiger Branches, das Bewahren von Kontext in der Historie.

Rebase

git checkout feature/my-feature
git rebase main

Spielt deine Commits auf dem Ziel-Branch neu ab. Erstellt eine lineare Historie – es sieht aus, als wäre das Feature auf Basis des aktuellen main entwickelt worden.

Vorher: A → B → C (main)
                 ↑
            D → E (feature, basierend auf B)

Nachher: A → B → C → D' → E' (feature auf C rebasiert)

Rebase verwenden für: das Bereinigen lokaler Commits vor einem PR, das Aktuellhalten von Feature-Branches.

Goldene Regel: Rebase niemals Commits, die bereits auf einen gemeinsam genutzten Branch gepusht wurden. Rebase schreibt die Historie um – das zerstört die lokalen Branches anderer Personen.

Interaktiver Rebase: Historie bereinigen

Vor dem Öffnen eines PRs können unordentliche Work-in-Progress-Commits zusammengefasst und bereinigt werden:

git rebase -i HEAD~4   # die letzten 4 Commits interaktiv bearbeiten

Optionen im interaktiven Editor:

  • pick — Commit beibehalten
  • squash — in den vorherigen Commit einbinden, Messages kombinieren
  • fixup — in den vorherigen Commit einbinden, Message verwerfen
  • reword — Änderungen beibehalten, Message bearbeiten
  • drop — Commit vollständig löschen

Konflikte lösen

Konflikte entstehen, wenn zwei Branches dieselben Zeilen verändern. Git markiert sie:

<<<<<<< HEAD (dein Branch)
const timeout = 5000;
=======
const timeout = 3000;
>>>>>>> feature/update-timeouts

Löse den Konflikt, indem du die Datei in den gewünschten Zustand bringst (Markierungen entfernen), und führe dann folgendes aus:

git add src/config.ts
git merge --continue   # oder git rebase --continue

Vorbeugung ist besser als Nachbehandlung:

  • Häufig von main pullen, um Branches kurzlebig zu halten
  • Mit Teamkollegen kommunizieren, wenn an denselben Dateien gearbeitet wird
  • PRs klein halten – große PRs haben mehr Konflikte und aufwendigere Reviews

Wichtige Alltagsbefehle

# Neues Feature starten
git checkout -b feature/my-feature

# Nur bestimmte Änderungen stagen (nicht die gesamte Datei)
git add -p

# Nicht gestagete Änderungen anzeigen
git diff

# Gestagete Änderungen anzeigen
git diff --staged

# Den letzten Commit nachträglich ändern (vor dem Pushen)
git commit --amend --no-edit

# Nicht committete Arbeit vorübergehend speichern
git stash
git stash pop

# Herausfinden, welcher Commit einen Bug eingeführt hat (binäre Suche)
git bisect start
git bisect bad              # aktueller Commit ist fehlerhaft
git bisect good v1.2.0      # letzter bekannt guter Commit

# Einen gelöschten Branch oder verlorenen Commit wiederherstellen
git reflog

# Branches visuell als Graph anzeigen
git log --oneline --graph --all

Best Practices für Pull Requests

Ein guter PR:

  • Macht eine Sache – Reviewer können die gesamte Änderung nachvollziehen
  • Hat eine klare Beschreibung – was geändert wurde, warum und wie es getestet werden kann
  • Ist klein – < 400 Zeilen Diff als grober Richtwert
  • Besteht die CI – bitte nie um ein Review bei einem fehlgeschlagenen Build
  • Verlinkt das IssueCloses #42 schließt das Issue automatisch beim Merge

Nutze unseren README Generator, um Dokumentation parallel zu deinen Code-Änderungen zu erstellen.

.gitignore-Grundlagen

Folgendes immer zur .gitignore hinzufügen:

# Umgebungsvariablen
.env
.env.local
.env.*.local

# Abhängigkeiten
node_modules/
vendor/

# Build-Ausgabe
dist/
build/
.next/

# Betriebssystemdateien
.DS_Store
Thumbs.db

# Editor-Dateien
.vscode/settings.json
.idea/
*.swp

Generiere eine projektspezifische .gitignore auf gitignore.io – dort sind Hunderte von Sprachen und Tools bekannt.

Git-Kenntnisse wachsen mit der Zeit. Verinnerliche das Denkmodell, gewöhne dir gute Commit-Gewohnheiten an – und die Zusammenarbeit deines Teams wird deutlich reibungsloser.