Files
fn_registry/docs/adr/0005-keep-parent-git-lean.md
T
egutierrez ea6a3ec8a5 chore: auto-commit (3 archivos)
- docs/adr/README.md
- docs/adr/0005-keep-parent-git-lean.md
- docs/diary/2026-06-03.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 12:50:09 +02:00

72 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR 0005 — Mantener el `.git` del repo padre ligero: no trackear artefactos hijos, purgar basura del historial, submódulos shallow
- **Fecha:** 2026-06-03
- **Estado:** accepted
## Contexto
El `.git` del repo padre `fn_registry` había crecido a **475 MB**, un tamaño que ralentiza clones, `fn sync` y la operación diaria entre los tres PCs del ecosistema (`aurgi-pc`, `home-wsl`, `lucas-linux`). El diagnóstico identificó tres causas independientes, todas evitables:
1. **Artefactos hijos forzados al índice.** Pese a que el `.gitignore` ya tiene las reglas correctas (`apps/*/`, `analysis/*/`, `projects/*/`), un `.gitignore` no des-trackea archivos que ya estaban en el índice. Dos apps tenían contenido forzado: `apps/dag_engine/` (31 archivos: código Go + frontend + `app.md` + `README.md`) y `apps/shaders_lab/` (`app.md` + un binario `shaders_lab.exe`). El commit `d8db05e9` ("chore(dag_engine): app.md ... metadata trackeada por el padre") había trackeado dag_engine deliberadamente; esta decisión queda **anulada**. La convención correcta ya estaba demostrada por `projects/*/apps` (p.ej. `registry_dashboard`, `call_monitor`), que el padre no versiona en absoluto y funcionan bien.
2. **Basura en el historial.** Versiones antiguas de directorios que nunca debieron versionarse seguían viviendo en los commits pasados: `frontend/node_modules` (168 MB de binarios), `build/` raíz (54 MB de artefactos de compilación C++, 2299 archivos), `registry.db` (29 MB en ~7 versiones; regenerable con `fn index`) y `apps/shaders_lab/shaders_lab.exe` (~190 MB acumulados en ~10 versiones). En total ~440 MB de blobs muertos.
3. **Submódulos C++ con historia completa.** `cpp/vendor/{imgui,implot,implot3d,tracy,glfw,sdl3}` + `emsdk` son submódulos git legítimos (deps necesarias para compilar las apps imgui). Cada uno clonaba **toda la historia upstream**: `.git/modules` pesaba 338 MB para servir un working tree de 118 MB. imgui solo: 129 MB de `.git` (11.552 commits) para 8.9 MB de headers; sdl3: 146 MB (21.539 commits) para 55 MB de código. El proyecto compila contra **un único commit pinneado** por submódulo — el resto es historia ajena que nadie consulta.
## Decisión
Mantener el `.git` del padre ligero con tres medidas:
1. **El repo padre NO versiona el contenido de los artefactos hijos.** Cada app/analysis/project-app es un sub-repo Gitea independiente con su propio `.git` (ADR 0002); el padre solo conserva su metadata en `registry.db` (regenerable con `fn index`, que lee los artefactos del disco). Se sacan del índice con `git rm -r --cached` (con `--cached` SIEMPRE — sin él se borraría el working tree de los sub-repos). Único contenido versionado bajo `apps/` y `analysis/`: los marcadores `.gitkeep`. Bajo `projects/`: solo los `project.md`.
2. **El historial pasado se purga de basura con `git filter-repo`.** Se eliminan los blobs de `frontend/node_modules`, `build/` (raíz), `registry.db` y `apps/shaders_lab/shaders_lab.exe` de todos los commits. Esto reescribe la historia (cambian los SHAs) y requiere `git push --force`. Se añade `build/` (raíz) al `.gitignore` para evitar reincidencia (`node_modules`, `*.exe` y `registry.db` ya estaban).
3. **Los submódulos C++ se configuran shallow (`depth 1`).** Cada submódulo descarga solo el commit pinneado, no la historia upstream. Se marca `shallow = true` en `.gitmodules` para que los clones futuros nazcan shallow. El working tree mantiene el snapshot completo de cada dependencia, así que la compilación C++ no cambia.
## Cómo se ejecutó (2026-06-03)
```bash
# 1. Untrack del índice (los archivos quedan en disco; los .git de los sub-repos conservan el código)
git rm -r --cached apps/dag_engine apps/shaders_lab
git commit -m "chore: untrack contenido de artefactos hijos (dag_engine, shaders_lab)"
# 2. Purga del historial (con git-filter-repo, descargado standalone)
python3 git-filter-repo --strip-blobs-bigger-than 10M --force
python3 git-filter-repo --invert-paths --path frontend/node_modules --path build \
--path registry.db --path apps/dag_engine --path apps/shaders_lab --force
git remote add origin <url> # filter-repo elimina el remote por seguridad
git push --force origin master
# 3. Submódulos shallow (deinit + borrar el .git/modules full + re-clone --depth 1)
for sm in cpp/vendor/{sdl3,imgui,tracy,glfw,implot,implot3d} emsdk; do
git submodule deinit -f "$sm"
rm -rf ".git/modules/$sm" # clave: deinit NO borra .git/modules
git -c "submodule.$sm.shallow=true" submodule update --init --depth 1 "$sm"
done
sed -i '/^\turl = /a\\tshallow = true' .gitmodules
git commit -m "chore: submodulos C++ en modo shallow (depth 1)" && git push origin master
```
Resultado: `.git` **475 MB → 51 MB** (89%). Desglose: `.git/objects` 137 MB → 16 MB (historial del registry limpio); `.git/modules` 338 MB → 35 MB (submódulos shallow). `cpp/vendor` en disco intacto (118 MB). `cmake configure` de `cpp/` OK con las deps shallow. Backup completo del `.git` pre-purga en `~/backups/fn_registry_purge_20260603/`.
## Alternativas descartadas
- **Solo `git rm --cached` sin purgar el historial.** Detiene el crecimiento futuro pero deja los ~440 MB de basura en los commits pasados. No reduce el `.git`. Insuficiente para el objetivo.
- **Purgar solo `shaders_lab.exe`.** Mismo coste (force-push + re-clone en otros PCs) por mucha menos ganancia: deja `node_modules`, `build/` y `registry.db` en el historial.
- **Borrar o purgar los submódulos C++.** Son deps legítimas necesarias para compilar las apps imgui. Purgarlas rompería la compilación. La vía correcta es shallow, no eliminación.
- **`git filter-branch` en vez de `git-filter-repo`.** Más lento, deja `refs/original` y es propenso a errores. `filter-repo` es la herramienta recomendada por el propio git.
## Consecuencias
- **Force-push reescribe la historia del padre.** Los otros PCs (`aurgi-pc`, `home-wsl`) quedan con historia divergente y deben re-sincronizar: `git fetch origin && git reset --hard origin/master && git submodule update --init --recursive`. Trabajo local del padre sin pushear se pierde — verificar antes. Esta es la única parte irreversible y outward-facing; requiere confirmación humana explícita.
- **Shallow es local y reversible.** No toca el repo padre ni los gitlinks; solo adelgaza el `.git` interno de cada submódulo. Reversible por dep con `git fetch --unshallow`. El `.gitmodules` con `shallow = true` hace que los clones frescos nazcan ligeros; los clones existentes deben re-aplicar el `deinit + rm .git/modules/<x> + update --depth 1` o re-clonar.
- **Bumpear una dep shallow cuesta un `git fetch --depth 1 <commit>` extra** antes del checkout, porque el commit nuevo no está en el clon mínimo. Es fricción, no bloqueo.
- **Se pierde `git log/blame/bisect` dentro de los submódulos** (la historia de SDL3/imgui), algo que casi nunca se hace en deps vendored.
- **Operación repetible.** Si el `.git` vuelve a crecer por basura, el procedimiento de este ADR (untrack + filter-repo + shallow) es el runbook.
## Relación con otras reglas y ADRs
- [ADR 0002](0002-apps-analyses-as-dataforge-master.md) — apps/analyses como sub-repos `dataforge/<name>`. Este ADR refuerza su corolario: el padre no versiona su contenido.
- `.claude/rules/apps_subrepo.md` — gotcha de pérdida de código en worktrees; misma raíz (artefactos = sub-repos independientes).
- `.claude/rules/db_locations.md``registry.db` solo en la raíz y regenerable; por eso es purgable del historial.