Commit-Messages und PR-Beschreibungen mit KI erstellen
Claude
>_
Claude Code · Git · Commit-Messages · Pull Requests
Commit-Messages und PR-Beschreibungen mit KI erstellen
Vom Diff zur Zusammenfassung, vom Was zum Warum

Claude Code erzeugt aus einem Diff in Sekunden eine strukturierte Commit-Message oder PR-Beschreibung und spart Schreibarbeit. Die Zusammenfassung beschreibt aber nur, was sich geändert hat, nicht warum. Dieser Artikel zeigt, wie Entwickler KI-Vorschläge sinnvoll nutzen und die inhaltliche Verantwortung behalten.

13 Min. Lesezeit Git · Conventional Commits · Pull Requests Claude Code CLI · CI-Integration

1. Warum Commit-Messages mehr sind als Pflichtübung

Eine Commit-Message ist die einzige Dokumentation, die untrennbar mit einer Code-Änderung verknüpft bleibt. Während Kommentare veralten und Tickets irgendwann archiviert werden, bleibt die Commit-Message über git blame und git log für immer an genau die Zeilen gebunden, die sie beschreibt. Wer in einem Jahr herausfinden will, warum eine bestimmte Preisberechnung in Magento auf eine bestimmte Art implementiert wurde, landet über git blame häufig schneller am Ziel als über eine Suche im Ticketsystem.

Genau deshalb ist die Versuchung groß, das Schreiben einer guten Commit-Message an eine KI zu delegieren. Claude Code sieht den Diff, kennt Konventionen wie Conventional Commits und formuliert in Sekunden einen Vorschlag, der grammatikalisch korrekt ist und die geänderten Dateien sauber benennt. Das Problem liegt nicht in der Sprache, sondern im Wissen: Ein Sprachmodell sieht nur den Code-Unterschied, nicht die Diskussion im Daily, das Kundengespräch oder den Grund, warum genau dieser Ansatz gewählt wurde und nicht ein anderer.

2. Wie Claude Code aus einem Diff eine Zusammenfassung ableitet

Technisch betrachtet arbeitet Claude Code beim Erzeugen einer Commit-Message rein textbasiert: Der Diff aus git diff --staged wird als Kontext übergeben, das Modell erkennt Muster wie geänderte Funktionssignaturen, neue Dateien, gelöschten Code oder angepasste Konfigurationswerte und leitet daraus eine plausible Beschreibung ab. Bei einer neuen Methode in einer Repository-Klasse erkennt das Modell zuverlässig, dass eine Methode hinzugefügt wurde, und meist auch, wofür sie technisch zuständig ist, etwa das Filtern einer Collection nach einem Attribut.

Was das Modell nicht ableiten kann, ist der Auslöser der Änderung. Ob die neue Filtermethode wegen eines Kundentickets, einer Performance-Regression oder eines geplanten Features entstanden ist, steht nirgends im Diff. Claude Code kann diese Lücke teilweise schließen, wenn zusätzlicher Kontext mitgegeben wird, etwa eine Ticketnummer, ein kurzer Hinweis auf die Motivation oder der Inhalt eines verlinkten Issues. Ohne diesen Kontext bleibt die generierte Message technisch korrekt, aber inhaltlich flach: Sie beschreibt die Diff-Oberfläche, nicht die Entscheidung dahinter.


#!/usr/bin/env bash
# Generate a commit message from the staged diff with Claude Code
set -euo pipefail

# Stage the relevant changes first
git add src/app/code/Mironsoft/SeoSuite/Model/CanonicalUrlResolver.php

# Ask Claude Code to draft a message, but provide the "why" explicitly
claude -p "Write a Conventional Commits message for the staged diff.
Context: fixes duplicate canonical URLs on paginated category pages
reported in ticket MIRO-482. Keep the subject line under 72 chars." \
  --allowedTools "Bash(git diff --staged)" "Bash(git log -5 --oneline)"

# Review before committing, never pipe the suggestion directly into commit
git commit -e -F <(echo "fix(seo): resolve duplicate canonical URLs on paginated category pages

Pagination parameters were included in the canonical URL builder,
causing page 2+ of a category to self-canonicalize instead of
pointing back to page 1. Fixes MIRO-482.")

3. Das Was und das Warum: die zentrale Lücke

Eine Commit-Message hat im Idealfall zwei Ebenen: die Betreffzeile beschreibt knapp, was sich geändert hat, der Body erklärt, warum diese Änderung nötig war und welche Alternativen verworfen wurden. Claude Code liefert die erste Ebene zuverlässig, weil sie direkt aus dem Diff ablesbar ist. Die zweite Ebene erfordert Wissen, das nur der Entwickler besitzt: den Kontext aus dem Sprint-Planning, die Einschätzung, dass ein einfacherer Fix riskanter gewesen wäre, oder die Information, dass ein Workaround bewusst temporär ist und in einem Folgeticket sauber gelöst wird.

Ein Beispiel aus der Magento-Praxis verdeutlicht den Unterschied: Ein Diff zeigt, dass ein Plugin auf Magento\Catalog\Model\Product::getPrice() hinzugefügt wurde. Claude Code beschreibt korrekt, dass ein neuer Preis-Plugin hinzugefügt wurde. Nur der Entwickler weiß, dass ein Preference an dieser Stelle bewusst vermieden wurde, weil ein anderes Drittanbieter-Modul dieselbe Klasse bereits überschreibt und ein Plugin-Konflikt sonst unvermeidlich wäre. Diese Begründung gehört in den Commit-Body, taucht in einem KI-generierten Vorschlag aber nur auf, wenn sie explizit mitgeteilt wird.

4. Praktisches Beispiel: vom Diff zur fertigen Commit-Message

Ein realistischer Ablauf beginnt damit, den Diff zu betrachten, bevor überhaupt ein KI-Vorschlag angefragt wird. Bei einer Änderung, die einen N+1-Query-Bug in einer Custom-Collection behebt, zeigt git diff --staged lediglich eine neue joinLeft()-Anweisung. Ein naiver KI-Vorschlag lautet dann oft schlicht "Update ProductCollection.php" oder allenfalls "Add joinLeft to ProductCollection". Beides ist technisch nicht falsch, aber für jeden, der den Commit später liest, wertlos.

Wird der Kontext mitgegeben, etwa "behebt N+1-Queries beim Laden von Custom-Attributen in der Produktliste, gemessen über New Relic mit 340 zusätzlichen Queries pro Seitenaufruf", entsteht eine deutlich brauchbarere Message. Der entscheidende Arbeitsschritt bleibt beim Entwickler: die generierte Betreffzeile prüfen, den Body um die Motivation ergänzen oder korrigieren, und erst danach committen. Claude Code liefert hier den ersten Entwurf und die saubere Formatierung nach Conventional-Commits-Konvention, nicht die fertige, freigegebene Aussage.


{
  "commit_draft": {
    "type": "fix",
    "scope": "catalog",
    "subject": "eliminate N+1 queries in product collection custom attribute loading",
    "body_ai_generated": "Added joinLeft() call to ProductCollection to fetch custom attributes in a single query instead of per-product lookups.",
    "body_after_human_review": "Custom attribute values were loaded per product inside a loop, causing 340 extra queries per category page (measured via New Relic APM). Replaced the per-product lookup with a single joinLeft() against eav_attribute_value, matching the pattern already used in OrderGridCollection. Trade-off: slightly larger result set per row, acceptable given the query count reduction.",
    "footer": "Refs: MIRO-511"
  }
}

5. PR-Beschreibungen strukturieren: Zusammenfassung, Kontext, Testplan

Eine Pull-Request-Beschreibung erfüllt eine andere Funktion als eine einzelne Commit-Message: Sie fasst mehrere Commits zu einer für Reviewer verständlichen Geschichte zusammen und muss zusätzlich erklären, wie die Änderung getestet wurde. Claude Code eignet sich gut, um aus mehreren Commit-Messages und dem Gesamt-Diff eines Branches eine erste Struktur mit den Abschnitten Zusammenfassung, Änderungen im Detail und Testplan zu erzeugen. Diese Struktur spart Zeit, weil das reine Aufzählen der geänderten Dateien und Funktionen eine mechanische Aufgabe ist.

Der Testplan-Abschnitt ist dabei der kritischste Teil, weil er nicht aus dem Diff ableitbar ist, sondern beschreiben muss, was tatsächlich manuell oder automatisiert geprüft wurde. Ein generierter Vorschlag wie "Tested locally" ist für einen Reviewer wertlos, weil er keine Aussage über den Umfang der Prüfung trifft. Erst eine konkrete Ergänzung wie "Getestet mit drei Warenkorb-Szenarien inklusive Gutschein-Kombination, Regressionstest der Checkout-Testsuite lokal ausgeführt" gibt dem Reviewer eine belastbare Grundlage für die Freigabe.


#!/usr/bin/env python3
"""ci-pr-description.py: draft a PR description from commit history.
Runs in CI, produces a template that a human reviews and completes
before opening the pull request. Does not auto-submit the PR.
"""
import subprocess
import sys

def get_commit_log(base_branch: str) -> str:
    """Return commit subjects and bodies since the base branch diverged."""
    result = subprocess.run(
        ["git", "log", f"{base_branch}..HEAD", "--pretty=format:%s%n%b%n---"],
        capture_output=True, text=True, check=True,
    )
    return result.stdout

def build_template(commit_log: str) -> str:
    """Build a PR description skeleton with mandatory sections."""
    return f"""## Summary
<!-- One or two sentences: what does this PR do and why now? -->

## Changes
{commit_log}

## Test plan
<!-- REQUIRED: describe what was actually verified, not just "tested locally" -->
- [ ] Manual test steps:
- [ ] Automated tests run:
- [ ] Edge cases considered:
"""

if __name__ == "__main__":
    base = sys.argv[1] if len(sys.argv) > 1 else "main"
    log = get_commit_log(base)
    print(build_template(log))

6. Typische Fallstricke generischer KI-Zusammenfassungen

Das häufigste Problem KI-generierter Commit-Messages ist Generik: Formulierungen wie "Update files", "Fix bug", "Improve code" oder "Refactor logic" sind technisch nicht falsch, aber inhaltsleer. Sie entstehen, wenn ein Modell ohne zusätzlichen Kontext auf einen großen, unübersichtlichen Diff trifft, der mehrere unabhängige Änderungen mischt, etwa einen Bugfix zusammen mit einer Formatierungsänderung und einem entfernten Debug-Statement. Je größer und heterogener der Diff, desto generischer fällt die Zusammenfassung aus, weil kein einzelner roter Faden mehr erkennbar ist.

Eine zweite Falle ist die übertriebene Sicherheit generierter Formulierungen. Ein Modell schreibt selbstbewusst "Fixes the checkout timeout issue", auch wenn die Änderung das Problem nur in einem von drei bekannten Szenarien behebt. Diese Übergeneralisierung ist gefährlich, weil sie im Reviewer und später im Team den Eindruck erweckt, ein Thema sei vollständig erledigt, obwohl es nur teilweise adressiert wurde. Der dritte häufige Fehler betrifft PR-Beschreibungen, die Testabdeckung suggerieren, die nie stattgefunden hat, weil das Modell einen plausibel klingenden Testplan erfindet, statt eine Lücke offen zu lassen.


#!/usr/bin/env bash
# commit-msg hook: reject generic subject lines before they enter history
set -euo pipefail

COMMIT_MSG_FILE="$1"
SUBJECT="$(head -n 1 "$COMMIT_MSG_FILE")"

# Common generic phrases produced by unreviewed AI drafts
GENERIC_PATTERNS=(
  "^(fix|feat|chore): (update|fix|improve) (files?|code|bug)$"
  "^update files?$"
  "^wip$"
  "^misc changes?$"
)

for pattern in "${GENERIC_PATTERNS[@]}"; do
  if [[ "$SUBJECT" =~ $pattern ]]; then
    echo "[REJECTED] Subject line is too generic: '$SUBJECT'" >&2
    echo "Describe what changed and, if relevant, why." >&2
    exit 1
  fi
done

exit 0

7. Warum der Autor die Zusammenfassung immer verifizieren muss

Die Verantwortung für Inhalt und Wahrheitsgehalt einer Commit-Message oder PR-Beschreibung liegt immer beim Autor, unabhängig davon, wer den Text ursprünglich formuliert hat. Ein Reviewer, der eine PR-Beschreibung liest, verlässt sich darauf, dass der beschriebene Testplan tatsächlich durchgeführt wurde und dass die genannte Motivation korrekt ist. Wird diese Annahme durch eine unkritisch übernommene KI-Zusammenfassung enttäuscht, verliert nicht nur der einzelne PR an Vertrauenswürdigkeit, sondern auch zukünftige PRs desselben Autors werden strenger geprüft.

Die praktische Konsequenz ist ein fester Verifikationsschritt vor jedem Commit: die generierte Betreffzeile gegen den tatsächlichen Diff lesen, prüfen, ob die genannte Motivation stimmt, und den Testplan nur übernehmen, wenn die beschriebenen Schritte wirklich ausgeführt wurden. Dieser Schritt dauert bei einer kurzen Commit-Message selten länger als eine Minute, verhindert aber systematisch, dass falsche oder übertriebene Aussagen in die dauerhafte Historie eines Repositorys gelangen. Wer diesen Schritt überspringt, verlagert die Verantwortung faktisch auf ein Werkzeug, das die eigentliche Motivation gar nicht kennen kann.

8. Automatisierung: Hooks, Aliasse und CI-Integration

Eine sinnvolle Automatisierung generiert Vorschläge, erzwingt aber an keiner Stelle eine ungeprüfte Übernahme. Ein Git-Alias oder ein prepare-commit-msg-Hook kann Claude Code aufrufen und den Vorschlag in die Commit-Message-Datei schreiben, die der Editor anschließend zur Bearbeitung öffnet, statt den Commit direkt abzuschließen. Dieser Zwischenschritt stellt sicher, dass jede generierte Message mindestens einmal gelesen wird, bevor sie in die Historie eingeht.

In CI-Pipelines eignet sich derselbe Ansatz für PR-Beschreibungen: Ein Skript erzeugt beim Öffnen eines Pull Requests einen Entwurf mit den Pflichtabschnitten Zusammenfassung, Änderungen und Testplan, aber ohne den PR automatisch zu veröffentlichen oder den Testplan-Abschnitt vorauszufüllen. So bleibt die mechanische Fleißarbeit automatisiert, während die inhaltliche Entscheidung, was tatsächlich getestet wurde, beim Menschen bleibt. Dieselbe Vorsicht gilt für automatisch generierte Changelogs aus Commit-Messages: Sie sind nur so gut wie die zugrunde liegenden Messages, und generische Einträge summieren sich zu einem für Kunden nutzlosen Änderungsprotokoll.


// generate-pr-draft.js: create a PR description draft via the Claude API
// Runs in a GitHub Action, posts the draft as a PR comment for human review
// instead of writing directly into the PR body.
const Anthropic = require('@anthropic-ai/sdk');
const { execSync } = require('node:child_process');

const anthropic = new Anthropic();

async function draftPrDescription(baseBranch) {
  const diff = execSync(`git diff ${baseBranch}...HEAD`, { maxBuffer: 10 * 1024 * 1024 }).toString();
  const log = execSync(`git log ${baseBranch}..HEAD --pretty=format:%s`).toString();

  const message = await anthropic.messages.create({
    model: 'claude-sonnet-4-5',
    max_tokens: 800,
    messages: [{
      role: 'user',
      content: `Draft a PR description with sections Summary, Changes, Test plan.
Mark the Test plan section as "NEEDS HUMAN INPUT", do not invent test steps.
Commit log:\n${log}\n\nDiff:\n${diff.slice(0, 8000)}`,
    }],
  });

  return message.content[0].text;
}

draftPrDescription('main').then(draft => {
  console.log('--- Draft for human review, not auto-posted ---');
  console.log(draft);
});

9. Commit-Messages im direkten Vergleich

Der Unterschied zwischen einer ungeprüften und einer verifizierten KI-Zusammenfassung wird am deutlichsten im direkten Vergleich konkreter Beispiele. Die folgende Tabelle stellt typische generische Vorschläge den überarbeiteten, kontextreichen Versionen gegenüber, wie sie nach einer kurzen menschlichen Prüfung entstehen sollten.

Situation Generischer KI-Vorschlag Verifizierte Version
Bugfix im Checkout fix: fix checkout bug fix(checkout): prevent double order creation on slow network retries
Neue Plugin-Klasse feat: add plugin feat(pricing): add tier-price plugin, avoids conflict with third-party discount module
PR-Testplan Tested locally Getestet mit 3 Warenkorb-Szenarien, Checkout-Testsuite lokal grün, kein Regressionstest für Guest-Checkout
Performance-Fix perf: improve performance perf(catalog): reduce category page queries from 340 to 12 via joinLeft
Konfigurationsänderung chore: update config chore(deploy): raise PHP memory_limit to 1G, resolves OOM on large CSV imports

Mironsoft

Magento- und Hyvä-Entwicklung mit KI-gestützten Workflows

Saubere Commit-Historie trotz KI-gestützter Entwicklung?

Wir richten Git-Workflows, Commit-Konventionen und PR-Vorlagen so ein, dass Claude Code Zeit spart, ohne dass die Aussagekraft eurer Projekt-Historie leidet.

Workflow-Audit

Bestehende Commit- und PR-Praxis auf Aussagekraft prüfen

Konventionen

Conventional Commits und PR-Vorlagen teamweit einführen

CI-Integration

Hooks und Skripte für PR-Entwürfe ohne Auto-Publish aufsetzen

10. Zusammenfassung

KI-gestützte Commit-Messages und PR-Beschreibungen sparen echte Schreibarbeit, weil sie die mechanische Aufgabe übernehmen, geänderte Dateien und Funktionen aus einem Diff zu benennen. Claude Code erkennt zuverlässig, was sich im Code geändert hat, kann aber nicht wissen, warum eine Änderung nötig war, welche Alternativen verworfen wurden oder welcher Testumfang tatsächlich abgedeckt wurde. Diese Lücke zwischen Was und Warum ist der zentrale Punkt, an dem menschliche Verifikation nicht optional, sondern notwendig bleibt.

Praktisch bewährt sich ein fester Ablauf: KI-Vorschlag als Entwurf behandeln, zusätzlichen Kontext wie Ticketnummern oder Motivation aktiv mitgeben, generische Formulierungen wie "Update files" oder "Tested locally" konsequent ersetzen, und jede Zusammenfassung vor dem Commit gegen den tatsächlichen Diff lesen. Automatisierung über Hooks und CI-Skripte funktioniert am besten, wenn sie Entwürfe erzeugt statt fertige Aussagen automatisch zu veröffentlichen.

Commit-Messages und PR-Beschreibungen mit KI - Das Wichtigste auf einen Blick

Was KI gut kann

Diff-Muster erkennen, Conventional-Commits-Format einhalten, mechanische Zusammenfassungen erzeugen.

Was KI nicht kann

Die Motivation hinter einer Änderung kennen, verworfene Alternativen benennen, echten Testumfang bestätigen.

Häufigster Fehler

Generische Formulierungen wie "Update files" oder erfundene Testpläne ungeprüft übernehmen.

Praxisregel

Kontext aktiv mitgeben, Vorschlag als Entwurf behandeln, vor jedem Commit gegen den Diff lesen.

11. FAQ: Commit-Messages und PR-Beschreibungen mit KI

1Kann Claude Code eine Commit-Message komplett eigenständig schreiben?
Technisch ja, basierend auf dem Diff. Inhaltlich beschreibt der Vorschlag nur das Was, nicht das Warum, und sollte vor dem Commit ergänzt werden.
2Warum sind KI-generierte Commit-Messages manchmal so generisch?
Bei großen, heterogenen Diffs findet das Modell keinen klaren roten Faden und formuliert allgemeine Aussagen wie "Update files".
3Was ist der Unterschied zwischen dem Was und dem Warum?
Das Was lässt sich aus dem Diff ableiten. Das Warum erklärt Motivation und verworfene Alternativen und muss aktiv mitgeteilt werden.
4Sollte ich einen KI-Vorschlag für eine PR-Beschreibung direkt übernehmen?
Nein, besonders der Testplan sollte nie ungeprüft übernommen werden, weil erfundene Testschritte möglich sind.
5Wie gebe ich Claude Code genug Kontext?
Mit einer kurzen Motivation im Prompt, etwa Ticketnummer, gemessener Effekt oder Begründung der technischen Lösung.
6Was ist Conventional Commits und hilft es bei KI-Messages?
Ein Format mit Typ und Scope, das Claude Code zuverlässig einhält. Ersetzt aber nicht die inhaltliche Prüfung.
7Wie automatisiere ich das, ohne die Kontrolle zu verlieren?
Über einen prepare-commit-msg-Hook, der den Entwurf zur Bearbeitung öffnet, statt den Commit automatisch abzuschließen.
8Können generische Commit-Messages ein Team-Problem werden?
Ja, automatisch generierte Changelogs basieren oft auf Commit-Messages und werden bei generischen Einträgen wertlos.
9Wer trägt die Verantwortung bei falschen Angaben?
Immer der Autor des PRs, unabhängig davon, wer den Text ursprünglich formuliert hat.
10Lohnt sich KI-Unterstützung trotz nötiger Verifikation?
Ja, weil die mechanische Arbeit real Zeit spart und die Verifikation eines guten Entwurfs meist nur Sekunden dauert.