CommunityCodierung & Entwicklunggithub.com

Wer hat geändert

Code der Person, dem Ticket, Branch und Pull Request zuordnen, die ihn erstellt haben – nur mit lokaler Git-Historie. Zeigt Autorenname, Commit-Hash, Ticketnummer, Branchname und Datum sowie Commit- und PR-Links.

Was ist Wer hat geändert?

Dieses Skill für Claude Code beantwortet die Frage „Wer hat diesen Code geschrieben, unter welchem Ticket und wann?“, ohne dass das Terminal verlassen werden muss. Es ersetzt die manuelle Suche durch einen einzigen Befehl, der die lokale Git-Historie nutzt und automatisch Commit-Hashes, Ticketnummern, Branchnamen, Autoren und PR-Links ermittelt. Das Skill unterstützt mehrere Modi: ganzes File (Top-Contributors + letzte Commits), Zeilenbereich (detaillierte Aufteilung pro Commit) und eine optionale „rohe“ Analyse ohne Whitespace-Ignorierung. Es funktioniert mit Bitbucket, GitHub und GitLab und erzeugt eine tabellarische Ausgabe, die der Assistent benutzerfreundlich formatiert. Wichtig: Es erfindet niemals Ticket-IDs oder Autoren, unterscheidet zwischen „gemerged über“ und „geschrieben in“ und gibt bei geringer Konfidenz explizite Warnungen aus. Es schreibt weder ins Repository noch ins Netzwerk und benötigt nur lokale Git-Daten.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Daniyal12333/claude-code-skills/tree/HEAD/who-changed

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht Wer hat geändert?

Beantworte „Wer hat das gebaut, unter welchem Ticket und wann?", ohne das Terminal zu verlassen. Alles Nötige ist bereits in der lokalen Git-Historie vorhanden. Der einzige Beitrag des Code-Hosts ist die PR-Erzählung, und die Ausgabe liefert einen Link dorthin.

Er ersetzt eine manuelle Schleife: Datei öffnen, Feature finden, Blame-Ansicht öffnen, Hash kopieren, in den Code-Host einfügen, zur PR klicken, Ticket und Autor ablesen.

Was der Benutzer bekommt

Autorenname, Commit-Hash, Ticketnummer, Branchname, Datum, PR-Nummer und klickbare Commit- und PR-Links. Ein Leiturteil für den Bereich, dann eine Tabelle aller Commits, die ihn berührt haben.

Skript ausführen

bash ~/.claude/skills/who-changed/scripts/who-changed.sh <datei> [start ende] [raw]

Wenn das Skill pro Projekt installiert ist, lautet der Pfad stattdessen .claude/skills/who-changed/scripts/who-changed.sh.

  • <datei> allein: Ganzes-Datei-Modus. Top-Contributors plus die letzten 12 Commits.
  • <datei> <start> <ende> (oder eine Zeilennummer): Zeilenbereich-Modus. Zeilenbesitz pro Commit.
  • raw anhängen: Blame ohne -w -C -M, für den Fall, dass der Benutzer die Byte-Ebene sehen möchte.

Umgebungsvariablen: WHO_CHANGED_BASE setzt den Ref, auf den die PR-Suche zusteuert (Standard: origin/HEAD, dann origin/main, origin/master, main, master); WHO_CHANGED_TICKET_REGEX ändert das Ticketmuster (Standard [A-Z][A-Z0-9]+-[0-9]+).

Das Skript gibt eine tabulatorgetrennte Ausgabe aus und schreibt niemals ins Repository oder ins Netzwerk. Formatiere es für den Benutzer um – füge das rohe TSV nicht ein.

Schritt 1: Ziel in einen Zeilenbereich auflösen

Das Skript erwartet Zahlen, daher muss ein Funktionsname zuerst in einen Bereich umgewandelt werden. Git's -L :funktionsname:-Kürzel hängt von einem sprachspezifischen Funktionsmuster ab und schlägt bei vielen Sprachen (insbesondere TypeScript-Klassenmitgliedern) mit no match fehl. Löse den Bereich selbst auf:

  1. Grepe nach der Deklaration, z. B. ^\s*(public|private|protected)?\s*(async\s+)?<name>\s*[(<], und <name>\s*[:=]\s*(function|\() für Arrow-Function-Eigenschaften. Für HTML oder CSS grepe nach dem wörtlichen Selektor, Schlüssel oder Block.
  2. Lies ab dieser Zeile und vergleiche die Klammern ab der ersten {, um die schließende Zeile zu finden.
  3. Wenn der Name an mehreren Stellen übereinstimmt, liste die Übereinstimmungen auf und frage, welche gemeint ist. Wähle niemals stillschweigend die erste – gebräuchliche Namen existieren oft in mehreren Dateien.

Die Zeilennummern stammen aus dem Arbeitsverzeichnis, sodass sie mit dem übereinstimmen, was der Benutzer in seinem Editor sieht.

Bei einem expliziten Bereich (285-300, 285, L285-L300) verwende ihn wie angegeben. Bei nur einem Dateipfad verwende den Ganzes-Datei-Modus.

Schritt 2: Ausgabe interpretieren

Der Block ## meta enthält base (der Ref, auf den die PR-Suche zusteuert), base_tip_date, web und host (Linkbasis, abgeleitet von git remote), den Blame-Modus und ob die Datei unbestätigte Änderungen hat.

Zeilen in ## commits sind nach besessenen Zeilen sortiert. Das Urteil ist die erste Zeile – der Commit, der die meisten Zeilen des Bereichs besitzt. Erwähne den Zweitplatzierten, wenn der Bereich wirklich geteilt ist; eine von vier Personen über drei Jahre erstellte Funktion sollte nicht als einer Person zugehörig gemeldet werden.

Das Skript erstellt bereits commit_url und pr_url für Bitbucket-, GitHub- und GitLab-Remotes. Wenn sie - sind, gibt es kein erkennbares Remote – sage das und lasse Links weg, anstatt einen Host zu erfinden.

Präsentiere es so (die Namen unten sind erfunden):

### calculateTotal - src/cart/cart.service.ts:42-61

**Alice Moreno** · `a1b2c3d` · 2023-02-08 · besitzt 13 von 20 Zeilen
Ticket SHOP-88 · Branch `SHOP-88-cart-totals` · PR #41

| Zeilen | Autor | Commit | Datum | Ticket | Branch | PR |
|---|---|---|---|---|---|---|
| 13 | Alice Moreno | a1b2c3d | 2023-02-08 | SHOP-88 | SHOP-88-cart-totals | #41 |
| 6 | Ben Carter | 9f8e7d6 | 2026-03-11 | SHOP-310 | SHOP-310-rounding-fix | nicht gemerged |
| 1 | Chen Wei | 4c5d6e7 | 2024-06-20 | — | release-2024-06 | #112 |

Dann die Links, dann eine Warnzeile, wenn ein Vertrauensindikator ausgelöst wurde.

Vertrauensindikatoren und was dazu zu sagen ist

IndikatorBedeutungSag dem Benutzer
okTicket-Branch über einen PR gemergedNichts nötig
local-onlyCommit ist noch nicht auf base„Noch nicht auf den Basis-Branch gemerged“ – es gibt keinen PR
no-pr-mergeAuf dem Hauptzweig, aber kein PR-Merge trägt ihnDirekt auf den Hauptzweig committet, oder der Merge-Subjekt hat die Konvention gebrochen
squashPR-Nummer aus einem (#123)-Suffix gelesenSquash-gemerged, daher ist die zeilenweise Historie innerhalb dieses PRs abgeflacht
low-no-ticketKein Ticket in der Nachricht oder im BranchGib an, dass kein Ticket aufgezeichnet wurde. Rate keins
low-integration-branchÜber einen Branch gemerged, der kein Ticket im Namen hatDer PR ist der Ort, an dem der Integrationsbranch gelandet ist, nicht wo der Code geschrieben wurde. Geringes Vertrauen
uncommittedNoch nicht committetLokale unbestätigte Änderungen; vom Urteil ausgeschlossen

Älterer Code kommt oft über langlebige Integrationsbranches (develop, release-*, ui-dev). Dafür ist die ehrliche Antwort „über PR #112 auf den Hauptzweig gemerged, aber dieser PR ist ein Integrationsbranch – es ist nicht der PR, in dem dieser Code geschrieben wurde.“

Warum -w -C -M der Standard ist

-w ignoriert Leerzeichen, -M folgt innerhalb der Datei verschobenen Zeilen, -C folgt aus einer anderen Datei kopierten Zeilen. Das ist nicht kosmetisch. Nimm einen Block, der 2023 geschrieben und erst 2026 neu eingerückt wurde (illustrative Zahlen):

  • intelligent (-w -C -M): 9 von 9 Zeilen gehen an den ursprünglichen Autor, 2023 – korrekt
  • roh: 8 von 9 Zeilen gehen an die Person, die neu eingerückt hat, 2026 – schreibt ihr alten Code zu

Der genannte Autor ist also die letzte Person, die das Verhalten geändert hat, nicht die letzte, die Bytes berührt hat. Sage das, wenn es darauf ankommt, und biete raw als Folgeaktion an.

Ehrlichkeitsregeln

  • Erfinde niemals eine Ticket-ID. Kein Ticket in der Commit-Nachricht oder im Branch: Melde — und sage, dass kein Ticket aufgezeichnet wurde.
  • Erfinde niemals einen Autor. Wenn die Schuldzuweisung nicht eindeutig ist, nenne die in Frage kommenden Commits.
  • Unterscheide „gemerged über“ von „geschrieben in“, wann immer ein Indikator mit geringem Vertrauen ausgelöst wird.
  • Wenn base_tip_date veraltet aussieht, weise darauf hin, dass der Basis-Ref seit kurzem nicht mehr abgerufen wurde und neuere Merges möglicherweise übersehen werden. Schlage git fetch origin vor – führe es nicht ungefragt aus.

Grenzen, die erwähnenswert sind, wenn relevant

  • Das „Warum“ ist nicht in Git. PR-Beschreibung, Reviewer und Ticket-Titel benötigen die API und Anmeldedaten des Code-Hosts oder Trackers. Der PR-Link ist der Übergabepunkt.
  • Squash-Merges flachen die Historie ab. Wenn ein PR gesquasht wurde, besitzt ein Commit das gesamte Feature und die zeilenweise Zuordnung darin ist verloren.
  • --ancestry-path wählt den ersten Merge, der den Commit auf den Hauptzweig gebracht hat. Bei verschachtelten Feature-Branches kann das ein Zwischen-Merge sein, nicht der PR des Tickets selbst.
  • Ganzes-Datei-Contributoren folgen keinen Umbenennungen. git shortlog hat kein --follow; die Commit-Liste folgt Umbenennungen, die Contributor-Liste nicht.
  • -C überrascht gelegentlich, indem es kopierten Code der Datei zuschreibt, aus der er stammt.
  • PR-Erkennung erkennt drei Merge-Nachrichtenstile: Bitbucket (Merged in <branch> (pull request #N)), GitHub (Merge pull request #N from ...), und Squash (... (#N)). Andere Stile fallen auf no-pr-merge zurück.

Fallback, wenn das Skript nicht verfügbar ist

git blame -w -C -M -L <start>,<ende> --date=short -- <datei>
git log -1 --date=short --pretty=format:"%H%n%an%n%ad%n%s%n%b" <sha>
git merge-base --is-ancestor <sha> origin/main     # kein Vorfahre -> ungemerged
git log --merges --ancestry-path --reverse --pretty=format:"%h|%s" <sha>..origin/main | grep -m1 "pull request"
git branch --contains <sha>                        # ungemerged-Fall

Analysiere den Merge-Subjekt auf Branch und PR-Nummer. Zwei Fallstricke: git shortlog benötigt ein explizites HEAD, sonst liest es stillschweigend von stdin und gibt nichts zurück, und Branchnamen können Präfixe haben (feature/SHOP-88-...), daher verankere den Ticket-Regex nicht am Anfang der Zeichenkette.

Verwandte Skills