CommunityProgramación y desarrollogithub.com

Daniyal12333/claude-code-skills

Atribuye el código a la persona, ticket, rama y pull request que lo produjo, usando solo el historial local de Git. Informa el nombre del autor, hash del commit, número de ticket, nombre de la rama y fecha, además de enlaces al commit y al PR.

¿Qué es claude-code-skills?

Esta skill permite determinar de manera precisa y rápida quién escribió, cambió o añadió código, y bajo qué ticket, rama o pull request se realizó. Utiliza exclusivamente el historial local de Git, sin necesidad de acceder a redes o APIs externas, y es compatible con Bitbucket, GitHub y GitLab. Funciona analizando archivos completos o rangos de líneas específicos, resolviendo nombres de funciones a rangos de líneas para una atribución exacta. Es especialmente útil en flujos de revisión de código, al atribuir autoría durante conversaciones o al investigar el origen de una funcionalidad. La salida incluye un veredicto principal y una tabla detallada de commits, con enlaces directos a los PRs y commits correspondientes. La skill también maneja casos complejos como fusiones squash, ramas de integración o commits sin ticket, aplicando reglas de honestidad para no inventar información.

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

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Quién Cambió

Responde "quién construyó esto, bajo qué ticket y cuándo" sin salir del terminal. Todo lo necesario ya está en el historial local de Git. Lo único que añade el alojamiento del código es la narrativa del PR, y la salida proporciona un enlace a ella.

Reemplaza el bucle manual: abrir el archivo, encontrar la funcionalidad, abrir la vista blame, copiar un hash, pegarlo en el alojamiento, navegar hasta el PR, leer el ticket y el autor.

Lo que obtiene el usuario

Nombre del autor, hash del commit, número de ticket, nombre de la rama, fecha, número de PR y enlaces en los que se puede hacer clic al commit y al PR. Un veredicto principal para el rango, seguido de una tabla de cada commit que lo tocó.

Ejecutar el script

bash ~/.claude/skills/who-changed/scripts/who-changed.sh <archivo> [inicio fin] [raw]

Si la skill está instalada por proyecto, la ruta es .claude/skills/who-changed/scripts/who-changed.sh.

  • <archivo> solo: modo de archivo completo. Principales contribuyentes más los últimos 12 commits.
  • <archivo> <inicio> <fin> (o un número de línea): modo de rango de líneas. Propiedad de líneas por commit.
  • Añadir raw: blame sin -w -C -M, para cuando el usuario quiera la verdad a nivel de byte.

Sobreescrituras de entorno: WHO_CHANGED_BASE establece la referencia hacia la que camina la búsqueda del PR (por defecto: origin/HEAD, luego origin/main, origin/master, main, master); WHO_CHANGED_TICKET_REGEX cambia el patrón del ticket (por defecto [A-Z][A-Z0-9]+-[0-9]+).

El script imprime un informe separado por tabuladores y nunca escribe en el repositorio ni en la red. Reformatee la salida para el usuario; no pegue el TSV sin procesar.

Paso 1: resolver el destino a un rango de líneas

El script acepta números, por lo que un nombre de función debe convertirse primero en un rango. El atajo -L :nombreFunción: de Git depende de un patrón de función específico del lenguaje, y para muchos lenguajes (miembros de clase en TypeScript en particular) falla con no match. Resuelva el rango usted mismo:

  1. Busque la declaración, por ejemplo ^\s*(public|private|protected)?\s*(async\s+)?<nombre>\s*[(<], y <nombre>\s*[:=]\s*(function|\() para propiedades de función flecha. Para HTML o CSS, busque el selector, clave o bloque literal.
  2. Lea desde esa línea y empareje llaves desde el primer { para encontrar la línea de cierre.
  3. Si el nombre coincide en más de un lugar, enumere las coincidencias y pregunte cuál. Nunca elija la primera silenciosamente; los nombres comunes suelen existir en varios archivos.

Los números de línea provienen del árbol de trabajo, por lo que coinciden con lo que el usuario ve en su editor.

Dado un rango explícito (285-300, 285, L285-L300), úselo tal cual. Dada solo una ruta de archivo, use el modo de archivo completo.

Paso 2: leer la salida

El bloque ## meta contiene base (la referencia hacia la que camina la búsqueda del PR), base_tip_date, web y host (base del enlace, derivada de git remote), el modo blame y si el archivo tiene cambios sin commit.

Las filas en ## commits están ordenadas por líneas de propiedad. El veredicto es la primera fila: el commit que posee la mayor parte del rango. Mencione al subcampeón cuando el rango esté realmente compartido; una función construida por cuatro personas a lo largo de tres años no debe informarse como perteneciente a una sola.

El script ya construye commit_url y pr_url para repositorios remotos de Bitbucket, GitHub y GitLab. Cuando son -, no hay un remoto reconocible; dígalo y omita los enlaces en lugar de inventar un anfitrión.

Preséntelo así (los nombres a continuación son inventados):

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

**Alice Moreno** · `a1b2c3d` · 2023-02-08 · posee 13 de 20 líneas
Ticket SHOP-88 · rama `SHOP-88-cart-totals` · PR #41

| Líneas | Autor | Commit | Fecha | Ticket | Rama | 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 | no fusionado |
| 1 | Chen Wei | 4c5d6e7 | 2024-06-20 | — | release-2024-06 | #112 |

Luego los enlaces, y luego una línea de advertencia cada vez que se active una bandera de confianza.

Etiquetas de confianza y qué decir sobre cada una

EtiquetaSignificadoDígale al usuario
okRama de ticket fusionada mediante un PRNada necesario
local-onlyEl commit aún no está en base"Aún no fusionado a la rama base" - no hay PR
no-pr-mergeEn la línea principal, pero ningún merge de PR lo transportaCommiteado directamente a la línea principal, o el asunto del merge rompió la convención
squashNúmero de PR leído de un sufijo (#123)Fusionado con squash, por lo que el historial línea por línea dentro de ese PR está aplanado
low-no-ticketSin ticket en el mensaje ni en la ramaIndique que no se registró ningún ticket. No adivine uno
low-integration-branchFusionado mediante una rama sin ticket en su nombreEl PR es donde aterrizó la rama de integración, no donde se escribió el código. Confianza baja
uncommittedNot Committed YetEdiciones locales sin commit; excluidas del veredicto

El código antiguo a menudo llega a través de ramas de integración de larga duración (develop, release-*, ui-dev). Para esos, la respuesta honesta es "fusionado a la línea principal mediante PR #112, pero ese PR es una rama de integración; no es el PR en el que se escribió esto".

Por qué -w -C -M es el valor por defecto

-w ignora espacios en blanco, -M sigue líneas movidas dentro del archivo, -C sigue líneas copiadas desde otro archivo. Esto no es cosmético. Tome un bloque que fue escrito en 2023 y solo re-indentado en 2026 (números ilustrativos):

  • inteligente (-w -C -M): 9 de 9 líneas van al autor original, 2023 - correcto
  • raw: 8 de 9 líneas van a la persona que re-indentó, 2026 - les acredita código antiguo

Entonces, el autor nombrado es la última persona en cambiar comportamiento, no la última en tocar bytes. Dígalo cuando sea relevante y ofrezca raw como seguimiento.

Reglas de honestidad

  • Nunca invente un ID de ticket. Sin ticket en el mensaje del commit ni en la rama: reporte — y diga que no se registró ningún ticket.
  • Nunca invente un autor. Si el blame no es concluyente, diga qué commits son candidatos.
  • Distinga "fusionado mediante" de "escrito en" cada vez que se active una bandera de baja confianza.
  • Si base_tip_date parece desactualizada, note que la referencia base no se ha obtenido recientemente y que pueden faltar fusiones recientes. Sugiera git fetch origin; no lo ejecute sin preguntar.

Límites que vale la pena mencionar cuando sea relevante

  • El "por qué" no está en Git. La descripción del PR, los revisores y el título del ticket necesitan la API y credenciales del alojamiento del código o del rastreador. El enlace al PR es el punto de traspaso.
  • Las fusiones squash aplanan el historial. Si un PR fue squasheado, un solo commit posee toda la funcionalidad y la atribución línea por línea dentro de él se ha perdido.
  • --ancestry-path elige el primer merge que llevó el commit a la línea principal. Con ramas de características anidadas, puede ser un merge intermedio, no el PR del propio ticket.
  • Los contribuyentes de archivo completo no siguen renombres. git shortlog no tiene --follow; la lista de commits sí sigue renombres, el recuento de contribuyentes no.
  • -C ocasionalmente sorprende al atribuir código copiado y pegado al archivo del que proviene.
  • La detección de PR reconoce tres estilos de mensaje de merge: Bitbucket (Merged in <rama> (pull request #N)), GitHub (Merge pull request #N from ...) y squash (... (#N)). Otros estilos caen en no-pr-merge.

Alternativa si el script no está disponible

git blame -w -C -M -L <inicio>,<fin> --date=short -- <archivo>
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     # no es ancestro -> no fusionado
git log --merges --ancestry-path --reverse --pretty=format:"%h|%s" <sha>..origin/main | grep -m1 "pull request"
git branch --contains <sha>                        # caso no fusionado

Analice el asunto del merge para la rama y el número de PR. Dos trampas: git shortlog necesita un HEAD explícito o lee silenciosamente la entrada estándar y no devuelve nada, y los nombres de rama pueden tener prefijo (feature/SHOP-88-...), por lo que no fije la regex del ticket al inicio de la cadena.

Skills relacionados