git pickaxe: encontrar el commit que introdujo una línea con git log -S y -G
Guía práctica del pickaxe de git para coding agents: cómo usar git log -S<string> para encontrar dónde cambió el número de ocurrencias de un texto, y git log -G<regex> para buscar commits cuyo parche toca líneas que encajan con un patrón. Incluye el ejemplo canónico frotz de la documentación oficial, comparativa lado a lado, checklist de depuración y errores típicos al buscar el origen de una línea en un repo ajeno.
Por Marco Lee · Reportar un error
Continúa con un curso prácticoEl pickaxe de git son las opciones -S y -G de git log, y buscan en todo el historial los commits que tocaron una cadena o un patrón concreto. Para un coding agent que llega a un repo ajeno, el pickaxe responde la pregunta "¿en qué commit apareció o desapareció esto?" sin recorrer cientos de commits a mano, y es complementario a git log para conjuntos de commits y al hub de comparativas y decisiones si el archivo existe en el working tree.
La diferencia entre -S y -G no es cosmética: uno cuenta ocurrencias y el otro mira el texto del parche. Elegir mal te hace perder commits que sí te interesan, o te obliga a revisar diffs irrelevantes.
Qué detecta cada uno: ocurrencias vs texto del parche
git log -S"<string>" lista los commits donde el número de ocurrencias de esa cadena cambio (subió, bajó o llegó a cero), considerando las versiones del archivo antes y después del commit. git log -G"<regex>" lista los commits cuyo patch contiene líneas añadidas o eliminadas que encajan con la expresión regular.
git log -S"<string>" | git log -G"<regex>" | |
|---|---|---|
| Qué busca | cambios en el número de ocurrencias de la cadena | líneas añadidas o eliminadas que encajan con la regex |
| Argumento por defecto | cadena literal | expresión regular extendida POSIX |
| ¿Regex? | solo con --pickaxe-regex | siempre |
| Detecta que movieron la línea sin cambiar la cuenta | no | sí |
| Caso de uso documentado | encontrar el origen de una cadena | encontrar commits que tocaron un patrón |
El ejemplo canónico de la documentación oficial de git: un commit modifica una llamada y el número de apariciones no cambia.
- hit = frotz(nitfol, mf2.ptr, 1, 0);
+ return frotz(nitfol, two->ptr, 1, 0);
git log -G"frotz\(nitfol" muestra ese commit. git log -S"frotz\(nitfol" --pickaxe-regex no lo muestra, porque la cadena frotz(nitfol aparece una vez antes y una vez después: su cuenta es la misma. Esa es la distinción que debes memorizar: -S solo reacciona cuando la cantidad de veces que aparece el texto cambia.

Cuándo usar -S
Usa -S cuando quieras el commit que introdujo o eliminó una cadena concreta, no un patrón:
- localizar dónde nació un nombre de función, una ruta o un endpoint
- encontrar el commit que dejó de usar una función (
git log -S"funcionDeprecada" --oneline) - detectar cuándo un valor mágico (una API key de prueba, un id de entorno) entró al historial
git log -S"framework.startApp()" --oneline -- src/
Agrega --pickaxe-all cuando el commit modificó varios archivos y quieres ver el diff completo, no solo el archivo donde está la cadena. Para el caso de "buscamos el origen de un texto", -S es exactamente la herramienta que describe la documentación.
Cuándo usar -G
Usa -G cuando la línea pudo cambiar de forma sin cambiar de cuenta:
- renombrado de variable o extracción a constante
- cambio de argumento en una llamada (el caso
frotz) - cualquier búsqueda por patrón, por ejemplo todos los commits que tocaron llamadas a
fetchen archivos TypeScript
git log -G"\.push\(" -p -- '*.ts'
-G es regex por defecto, sin necesidad de --pickaxe-regex. Si además quieres el diff del commit candidato, combínalo con -p y confirma con git show <sha> antes de afirmar nada en el reporte.

Combinar con el resto del flujo git
El pickaxe escanea blobs, así que en repos grandes conviene acotar antes de ejecutar:
- ruta:
git log -S... -- src/services/limita el escaneo a esa subárbol - rango:
--since,--until, y-n 10para no inundar la salida - todas las ramas:
--allcuando el commit pudo venir de una rama ya fusionada - tipo de cambio:
--diff-filter=Apara commits que solo añadieron,-Dpara borrados - binarios: sin un filtro textconv, los binarios se ignoran; con
--texttambién se escanean
No confundas el pickaxe con git log --grep, que busca en los mensajes de commit, ni con git blame, que atribuye las líneas actuales a una versión concreta. El pickaxe trabaja sobre el contenido del diff a lo largo de la historia.
Checklist para depurar con pickaxe
- ¿Cadena literal o patrón?
-Svs-G(o-S+--pickaxe-regex) - ¿La cuenta pudo no cambiar? Entonces es
-G, no-S - ¿Acoté por ruta y por rango de fechas antes de correr?
- ¿Lo confirmé con
git show <sha>y vi el parche real? - ¿Necesito todo el changeset?
--pickaxe-all - ¿El resultado está vacío? Prueba
--allo quita el filtro de ruta - ¿Texto binario? Añade
--texto un filtro textconv
FAQ
¿Por qué git log -S"frotz\(nitfol" --pickaxe-regex no muestra el commit que modifica esa línea? Porque -S solo reacciona a cambios en el número de ocurrencias; si la cadena sigue apareciendo la misma cantidad de veces, el commit no califica. Para "el parche toca líneas que encajan con un patrón" usa -G, que no necesita --pickaxe-regex.
¿-S es siempre literal? Sí, salvo que pases --pickaxe-regex, que trata el argumento de -S como una expresión regular extendida POSIX.
¿Pickaxe y git log --grep son lo mismo? No. --grep filtra por el mensaje del commit; el pickaxe analiza el contenido del diff.
¿Detecta renombrados? -G sí, porque mira líneas del parche. -S detecta el cambio de cuenta, no la renombrada en sí: si el símbolo aparece igual cantidad de veces, no lo reporta.
¿El pickaxe tarda mucho? En repos grandes conviene acotar por ruta y rango; git log -S... -- src/ es notablemente más rápido que sin límite. Si el historial es enorme, revisa git commit-graph para acelerar el recorrido.
Resumen
-S responde "¿cuándo cambió la cuenta de esta cadena?" y -G responde "¿qué commits tocaron líneas que encajan con este patrón?". Acota por ruta y rango, confirma con git show, y usa --pickaxe-all para contexto completo. Con eso, encontrar el origen de una línea en un repo ajeno pasa de caracolear en git log a una consulta con respuesta en segundos. Si trabajas con repos compartidos, recuerda también el flujo seguro de worktrees para no contaminar tu rama mientras investigas.
De la guía a la práctica
Pi agent (Pi.dev): instala tu agente de coding
Lleva tus convenciones de trabajo a Pi.dev: instalación, instrucciones, sesiones y operación segura.
Ver el curso gratisContenido gratis, sin registro. Los servicios externos pueden tener costos.
Avisos cuando actualicemos cursos y guías
Recibe actualizaciones por correo. Es opcional: puedes seguir leyendo y abrir cualquier curso sin suscribirte.
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.



