Guía9 min

git commit-graph para coding agents: índice de historia, no gc

Resumen

git commit-graph write serializa padres, fechas y generation numbers en objects/info. verify comprueba el archivo contra la object database. Un agente puede verificar. Cero write autónomo en el clone del humano. Cero --split=replace. Cero --changed-paths. Distinto de gc, maintenance y fsck. Git 2.50.1.

GitHub
Índice serializado de commits: generation numbers y padres; HEAD y el working tree no se mueven

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 commit-graph escribe y verifica el archivo serializado del grafo de commits. El man (git-commit-graph(1); git-scm.com/docs/git-commit-graph HTTP 200, last-modified 2026-08-31; pie del man local Git 2.50.1.428.g0e8243, 2025-07-22; binario Git 2.50.1 / Apple Git-155): Write and verify Git commit-graph files. SYNOPSIS: git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress] · git commit-graph write [--object-dir <dir>] [--append] [--split[=<strategy>]] [--reachable | --stdin-packs | --stdin-commits] [--changed-paths] [--[no-]max-new-filters <n>] [--[no-]progress] <split-options>.

El formato (gitformat-commit-graph(5)): lista de OIDs, generation number, root tree, fecha, padres por índice posicional y, si se pidió, Bloom filter de paths cambiados vs el primer padre. Vive en $GIT_DIR/objects/info/commit-graph o en objects/info/commit-graphs/* si es cadena split. No es un pack. No es un reflog. No mueve HEAD.

No es gc. gc may also update ancillary indexes such as the commit-graph (gc.writeCommitGraph default true). commit-graph solo toca ese índice. Tampoco es maintenance: el task commit-graph de maintenance escribe incremental y luego verifica; el orquestador no es este comando. No es fsck: fsck camina objetos; verify camina el archivo.

Contrato: git commit-graph verify. Cero write autónomo. Cero --split=replace. Cero --changed-paths. Cero --object-dir ajeno. Cero en el clone del humano salvo que el humano lo pida.

Qué hace (y qué no)

core.commitGraph default true: Git lee el archivo si existe (git-config(1)). Escribirlo es otro verbo. El man de write: Write a commit-graph file based on the commits found in packfiles. Si core.commitGraph está disabled, write imprime un warning, retorna success y no escribe. No es un error. Un agente que “arregla” el warning reescribiendo config viola config.

Tres formas de elegir commits (mutuamente excluyentes):

FlagQué caminaCuándo
--reachablecommits desde todas las refsel default razonable si el humano pide write
--stdin-packsobjetos solo en los pack-indexes de stdinmantenimiento de packs, no un agente
--stdin-commitswalk desde OIDs hex, uno por línearecorte; OIDs malformados o inexistentes = error; no-commits se ignoran

Sin uno de esos tres, write usa los commits ya packed. --append incluye los que ya estaban en el archivo existente.

--split escribe una cadena en info/commit-graphs. El tip nuevo se fusiona con el anterior según --size-multiple (default 2) y --max-commits. --split=no-merge nunca fusiona. --split=replace tira la cadena y escribe una de longitud 1. Un agente no usa replace.

--changed-paths calcula Bloom filters de paths vs el primer padre. El man: This operation can take a while on large repositories y future commit-graph writes will automatically assume that this option was intended. Es sticky. --no-changed-paths para parar. --max-new-filters=<n> limita filtros nuevos (-1 = sin techo). Un agente no enciende Bloom filters en el clone del humano.

verify lee el archivo y lo compara con la object database. --shallow en una cadena split solo mira el tip. Verificado 2026-09-06 en este repo (Git 2.50.1 / Apple Git-155): git commit-graph verify → stdout vacío, exit 0.

Un coding agent verifica el commit-graph contra la object database; no reescribe el archivo

Por qué un agente se equivoca

Un coding agent ve git log lento y “optimiza” con git commit-graph write --changed-paths --split=replace. Tres errores:

  1. --changed-paths es caro y persistente. El siguiente write asume Bloom filters. El clone del humano queda con un índice que Git viejo puede no leer (commitGraph.changedPathsVersion 2 vs Git antiguo).
  2. --split=replace reescribe la cadena entera. El task de maintenance will not expire .graph files that were in the previous commit-graph-chain; replace no tiene esa cortesía.
  3. No es el cuello de botella. Si log -- path duele, el humano pide Bloom filters. Si merge-base duele, generation numbers ya van en un write --reachable normal. Adivinar no es el contrato.

Otro fallo: write --object-dir apuntando a un alternate. Si el path no es absoluto o no coincide con un object dir conocido, el comando sale non-zero. Un agente no inventa directorios.

Tercero: mezclar git gc y git commit-graph write en el mismo turno. gc ya puede reescribir el grafo (gc.writeCommitGraph). Dos writers concurrentes sobre objects/info/ no son “por si acaso”.

Contrato para el agente

Sí, sin preguntar

  • git commit-graph verify
  • git commit-graph verify --shallow si el humano habla de cadena split
  • Reportar exit code. 0 = el archivo cuadra con la object database. Non-zero = corrupto o ausente de forma que verify no traga; no “lo regenero”

Solo si el humano lo pide, y en este orden

  1. git commit-graph verify (baseline)
  2. git commit-graph write --reachable --split
  3. git commit-graph verify otra vez

--reachable --split es lo más cerca del task incremental de maintenance: tip nuevo, merge por tamaño, sin replace. --progress solo si hay TTY; en cron, --no-progress.

Nunca

  • write autónomo en el clone del humano
  • --split=replace
  • --changed-paths / --no-changed-paths (el segundo también cambia política)
  • --stdin-packs o --stdin-commits inventando OIDs
  • --object-dir que no sea el object dir de este repo
  • --append “por si acaso” sobre un grafo que no has leído
  • reescribir core.commitGraph, gc.writeCommitGraph, commitGraph.*
  • git gc --aggressive “para que escriba el grafo”
  • borrar a mano objects/info/commit-graph o commit-graphs/

Relación con maintenance y gc

El hub de comparativas ya separa los verbos. Tabla corta:

ComandoQué tocaAutónomo
commit-graph verifylee el índice
commit-graph writeescribe objects/info/no
maintenance run --auto --quietorquesta; task commit-graph hourly en strategy incrementalel contrato de maintenance, no este comando
gc --auto --quiethousekeeping; puede reescribir el grafoel contrato de gc
fsckobjetosdiagnóstico, no índice

git maintenance register pone commit-graph: hourly y apaga auto-gc de primer plano. Un agente no “registra para ayudar”. Si el humano quiere el índice al día, el scheduler de maintenance es el sitio; este binario es el ladrillo.

commitGraph.generationVersion default 2 (corrected commit dates). Poner 1 a mano deja de escribir/leer esas fechas. commitGraph.changedPathsVersion default -1 (usa lo que haya; si no hay, escribe v1). Valores > 1 may be incompatible with older versions of Git. Un agente no pincha versiones.

Checklist

  • ¿Solo necesitabas saber si el índice está sano? → verify
  • ¿El humano pidió write? → --reachable --split, luego verify
  • ¿Alguien sugirió --changed-paths? → no, salvo petición explícita y aviso de que queda sticky
  • ¿Hay un gc o maintenance run en el mismo turno? → no lances write a la vez
  • ¿Vas a tocar core.commitGraph? → no
  • ¿El path de --object-dir no es este repo? → aborta

Cadena split del commit-graph: tip incremental, sin replace

FAQ

¿Puedo borrar objects/info/commit-graph si verify falla? No. Reporta el exit code. Borrar el archivo a mano deja a Git sin índice; el siguiente log no se “arregla”, solo camina más lento. El humano decide si write --reachable --split o si hay corrupción real (entonces fsck).

¿write sin flags es seguro? Escribe según packs locales. En un clone con alternates o partial clone puede quedar corto. --reachable es el default que pedimos si el humano autoriza. Sigue siendo write: no autónomo.

¿Por qué no --stdin-commits con HEAD? El ejemplo del man (git rev-parse HEAD | git commit-graph write --stdin-commits --append) es válido como receta humana. Un agente que mete HEAD y olvida --append tira commits que ya estaban en el grafo y no son ancestros de HEAD.

¿Verify reescribe? No. Solo lee. --shallow no repara: limita el chequeo al tip.

¿Esto acelera git status? No. El commit-graph acelera caminar historia (log, merge-base, generation). status mira working tree e index.

Fuentes

Verificado 2026-09-06: man local git-commit-graph(1) / gitformat-commit-graph(5) / git-maintenance(1) / git-gc(1) / git-config(1) (Git 2.50.1 / Apple Git-155); git-scm.com/docs/git-commit-graph HTTP 200, last-modified 2026-08-31. git commit-graph verify en este repo: exit 0.