CLI AI

git bisect: encuentra el commit que lo rompió

2026-07-20

git bisect start && git bisect bad && git bisect good <hash-viejo> arranca una búsqueda binaria por el historial, y git bisect run ./check.sh la termina sin una sola respuesta manual. Decide el código de salida del script: 0 es bueno, distinto de cero es malo y 125 significa "este commit no se puede juzgar, sáltalo".

1. Marca los límites

clai
$ clai empieza a buscar el commit que rompió la suma, el bueno conocido es fa5873a→ git bisect start && git bisect bad && git bisect good fa5873aBisecting: 4 revisions left to test after this (roughly 2 steps)[37a14229ef73e1801a49defb16a86a26c122aa41] refactor step 5

bad sin argumento significa el HEAD actual. Git salta de inmediato a la mitad del rango y te dice cuántos pasos quedan: diez commits son tres o cuatro comprobaciones, mil son diez.

2. Responde en cada paso

clai
$ clai este commit funciona bien→ git bisect goodBisecting: 2 revisions left to test after this (roughly 1 step)[cbae02ada1b9e211691957bc7daff38a214a5a13] speed up addition

Pruebas, respondes good o bad y git avanza. Cada respuesta descarta la mitad de lo que queda.

3. La respuesta

clai
$ clai este commit está roto→ git bisect badcbae02ada1b9e211691957bc7daff38a214a5a13 is the first bad commitcommit cbae02ada1b9e211691957bc7daff38a214a5a13Author: Demo <[email protected]>Date:   Thu Aug 27 22:52:21 2026 +0700    speed up addition calc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)

Git nombra el primer commit malo e imprime su diffstat de inmediato. Un git show <hash> después queda claro que "speed up addition" cambió un más por un menos.

4. Lo mismo sin ninguna respuesta manual

clai
$ clai encuentra el commit culpable automáticamente, la prueba es ./check.sh→ git bisect run ./check.shrunning './check.sh'Bisecting: 0 revisions left to test after this (roughly 0 steps)[e0991601aa7cd6c25d3ac78b486319a7ee55713e] refactor step 6running './check.sh'cbae02ada1b9e211691957bc7daff38a214a5a13 is the first bad commitbisect found first bad commit

Esta es la parte que vale la pena recordar. El script devuelve 0 para un commit bueno y cualquier cosa distinta de cero para uno malo, y puede ser una sola línea: test "$(./calc.sh 2 3)" = "5".

5. Commits que ni siquiera compilan

clai
$ clai salta los commits que no compilan→ git bisect run ./check125.sh

El código 125 es especial: significa "de este commit no se puede opinar, sáltalo". Ese paso aparece en git bisect log como una línea # skip:. La forma habitual es: falló la compilación → exit 125, falló la prueba → exit 1.

6. Vuelve al punto de partida

clai
$ clai termina el bisect y devuélveme a mi rama→ git bisect resetPrevious HEAD position was cbae02a speed up additionSwitched to branch 'main'

Durante un bisect el repositorio está en detached HEAD. reset te devuelve a la rama desde la que empezaste. Si lo olvidas, pasarás la tarde preguntándote por qué tu copia de trabajo está llena de código viejo.

Gotchas

  • Una respuesta equivocada arruina toda la búsqueda. Probado en un repositorio real: responder bad en vez de good en un solo paso hizo que git culpara a e099160 en lugar del verdadero cbae02a. La cura es git bisect log: guárdalo, corrige la línea mala y repítelo con git bisect replay.
  • git bisect run lee códigos de salida, no la salida. Un script que imprime "FAILED" y sale con 0 cuenta como éxito. Cualquier valor por encima de 127 aborta el bisect entero.
  • Guarda el script de prueba fuera del repositorio. Un archivo sin seguimiento sobrevive a los checkouts, pero un script que solo existe en los commits recientes desaparecerá en cuanto git salte a uno antiguo, y se lleva tu bisect con él.

Related questions

¿Y si no conozco ningún commit bueno? Toma uno obviamente viejo: git bisect good HEAD~200. Si también está roto, git te lo dice en el primer paso.

¿Puedo bisecar por una cadena de la salida? Sí, con cualquier comando: git bisect run sh -c '! ./app 2>&1 | grep -q "NullPointer"'. Lo único importante es que 0 signifique bueno.

¿Cómo veo qué cambió el commit culpable? git show <hash> imprime el diff completo, git show --stat <hash> solo la lista de archivos.

See also

CliAI escribe los comandos de bisect y el script de prueba de una línea a partir de una descripción normal, y los muestra antes de ejecutar nada. Instálalo en una línea.