Guía9 min

git range-diff para coding agents: dos series, no un diff

Resumen

git range-diff compara dos versiones de una serie. Tres args. --no-color. = igual, ! cambió, > nuevo, < desapareció. Cero --stat. La salida no es un parche. Git 2.50.1.

GitHub
Dos series de commits se alinean: iguales, cambiados, añadidos o desaparecidos; HEAD no se mueve

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

git range-diff compara dos versiones de una serie de parches. El man (git-range-diff(1); git-scm.com/docs/git-range-diff HTTP 200, last-modified 2026-08-31; pie del man local Git 2.54.0, 2026-04-19; binario Git 2.50.1 / Apple Git-155): Compare two commit ranges (e.g. two versions of a branch). SYNOPSIS: <range1> <range2> / <rev1>...<rev2> / <base> <rev1> <rev2>.

No es diff. diff compara trees. range-diff compara series: author, mensaje y parche de cada commit contra su pareja. HEAD no se mueve. El working tree no importa.

Tampoco es cherry. cherry responde “¿este parche ya está en upstream?” con +/-. range-diff responde “¿qué cambió entre dos iteraciones de la misma serie?”.

Contrato: git range-diff --no-color <base> <old-tip> <new-tip>. Tres args. Cero invocación sin rangos. Cero --stat. Cero tratar la salida como parche.

Qué hace (y qué no)

El man: shows the differences between two versions of a patch series, or more generally, two commit ranges (ignoring merge commits). Empareja commits del rango viejo con los del nuevo por “diff of diffs”. El orden de la salida sigue el rango nuevo. Tres formas (man):

  • <range1> <range2>: cada uno base..tip, rev^! o rev^-n.
  • <rev1>...<rev2>: equivalente a <rev2>..<rev1> vs <rev1>..<rev2>.
  • <base> <rev1> <rev2>: equivalente a <base>..<rev1> vs <base>..<rev2>.

Marcas (man, EXAMPLES):

MarcaSignificado
=pareja equivalente (mismo parche; el SHA puede ser otro)
!pareja con cambios (mensaje o diff distintos)
>commit nuevo (no hay pareja en el viejo)
<commit desapareció (estaba en el viejo, no en el nuevo)

Verificado 2026-09-06 (Git 2.50.1 / Apple Git-155). Repo base → topic A/B/C; main avanza; rebase de topic sobre main:

  • git range-diff --no-color main ORIG_HEAD HEAD: 0. Tres líneas =. SHA distintos a izquierda y derecha. El parche no cambió.
  • git range-diff --no-color main topic@{1} topic: 0. Igual. Receta del man tras un rebase: git range-diff @{u} @{1} @.
  • Mensaje-only (TODO: Describe a bugDescribe a bug, mismo tree): 0. A y C con =; B con ! y hunk @@ Metadata del mensaje.
  • Rewrite grande (three vs THREE en un blob de una línea): 0. B viejo con <, B nuevo con >. No empareja.
  • --left-only con A igual, B y C solo en old, D solo en new: 0. = de A y < de B y C. No imprime > de D.
  • --right-only: 0. = de A y > de D. No imprime <.
  • Working tree sucio: 0, misma salida. rev-parse HEAD igual que antes.
  • Sin args / un solo arg: 129, need two commit ranges.
  • --foo: 129, unknown option `foo'.
  • Fuera de un repo: 128, not a git repository.
  • --stat en el caso !: 0. La tabla de marcas sale; el “stat” pisa el hunk útil (a => b | 2 +-). El man (OUTPUT STABILITY): quite useless in the context of range-diff.

La sección OUTPUT STABILITY del man: la salida es porcelain para humanos. No hay --stable. No hay equivalente de apply. Un agente no la parsea ni la reaplica.

Dos series alineadas: iguales, un commit cambiado y uno nuevo; HEAD no se mueve

Lo que el agente sí / no corre

QuieroComandoTrampa
¿El rebase reescribió el parche?git range-diff --no-color <base> <old> <new>diff old new (compara tips, no la serie)
Receta post-rebasegit range-diff --no-color @{u} @{1} @sin rangos: 129
Solo lo que desapareció--left-onlydump de log -p
Solo lo que apareció--right-onlytratar > como “pickea ya”
Color para un humanodefault dual-colorvolcar ANSI a un LLM
Para el LLM--no-color--stat (man: output quite useless)

Prohibido en autónomo:

  • Sin rangos. Verificado: 129. Un agente no “adivina” @{u} si no hay tracking.
  • --stat, --name-only, --raw. El man: opciones de diff pueden producir salida inútil; futuras versiones pueden reinterpretarlas.
  • Tratar la salida como parche. No hay git apply de un range-diff. Un ! no es un hunk aplicable.
  • Confundirlo con diff. git diff old new es un tree. range-diff es commit a commit.
  • Confundirlo con cherry. cherry mira un upstream. range-diff mira dos series.
  • --creation-factor a ciegas. Default 60. El man: súbelo si un cambio grande se ve como delete+add; bájalo si empareja de más. Un agente no lo tunear. Verificado: three vs THREE sale </> con 60 y con 90.
  • --diff-merges / --remerge-diff autónomo. Por defecto ignora merges.
  • Volcar dual-color a un prompt. --no-color.
  • Usar SHA cortos de la salida para el siguiente comando. Son porcelain.
  • Correr rebase “porque salió un !”. range-diff solo imprime.

Receta (60 segundos)

Solo en un worktree propio. Tres args explícitos:

git status -sb
git range-diff --no-color -- "$base" "$old_tip" "$new_tip"
echo $?

Tras un rebase que acabas de terminar, la receta del man:

git range-diff --no-color -- "@{u}" "@{1}" "@"
  • 0 y líneas =: la serie se reescribió de SHA, el parche no. Reporta “equivalente” y para.
  • 0 y un !: ese commit cambió. Reporta el subject. Cero rebase extra. Cero amend.
  • 0 y > / <: commits añadidos o caídos. Reporta la lista. Cero pick automático.
  • 129: faltan rangos u opción desconocida. No reintentes con flags de diff.
  • 128: no hay repo.

Cierre = la tabla de marcas. Cero commit. Cero push a main.

El working tree sigue igual; range-diff solo imprime la tabla de la serie

range-diff vs diff vs cherry vs rebase

diff compara snapshots. Útil para “qué hay en el working tree”. Inútil para “¿el rebase tocó el parche de B?”: el tip cambió sí o sí.

cherry pregunta si un parche ya vive en upstream (+/- por patch-id). range-diff pregunta cómo mutó una serie entre dos tips. Un - de cherry no te dice si el mensaje se reescribió; un ! de range-diff sí.

rebase aplica. Mueve HEAD, reescribe SHA, puede dejar el árbol a medias. range-diff mira dos rangos ya existentes. El man pone el ejemplo justo después del rebase, no como sustituto.

--creation-factor (default 60) es el fudge del matching: costo de “este commit es nuevo” vs “es una reescritura”. El algoritmo (man, ALGORITHM) arma una matriz de costos y resuelve asignación. Un agente no lo retoca.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. range-diff no es diff: compara series, no trees.