Capítulo 30 de 33 11 secciones 7 min

Git es el cinturón de seguridad cuando trabajas con IA

Por qué esto importa más ahora que hace cinco años

<strong>Commit antes de pedirle nada.</strong> Esa sola costumbre convierte cualquier cambio de una IA en algo que puedes mirar con <code>git diff</code>, aceptar por partes o deshacer entero con <code>git restore</code>. Sin ese commit previo no tienes con qué comparar y el cambio llega mezclado con tu propio trabajo. Y una segunda costumbre: revisar siempre lo que entra, porque quien firma el commit eres tú.

Este libro existe por una razón muy concreta, y es de 2026: hay muchísima gente que llegó a GitHub sin haber programado nunca, empujada por la IA. Buscan Claude Code, buscan skills, buscan proyectos, y todo eso vive en repositorios 🤖

Y resulta que Git, que era una herramienta de programadores, se volvió lo que más falta hace cuando trabajas con IA. Por una razón simple: los cambios ya no los escribes tú de a uno, llegan de golpe.

El problema nuevo

Cuando escribes tú, vas viendo. Cuando le pides a una IA que reorganice el proyecto, en un minuto hay seis archivos cambiados, uno borrado y una carpeta nueva. Si eso no funciona, ¿qué parte falló? 🤔

Git contesta esa pregunta, pero solo si hiciste una cosa antes.

La costumbre que lo cambia todo

mkdir analisis-ventas
cd analisis-ventas
git init -q
printf 'ciudad,monto\nLima,1200\nArequipa,890\n' > ventas.csv
printf 'import csv\n\ntotal = 0\n' > reporte.py
git add .
git commit -q -m "Primera version del reporte de ventas"
git status --short
echo "todo guardado, ahora si puedo pedir cambios"
todo guardado, ahora si puedo pedir cambios

Diez segundos. Y con eso ya tienes un punto de retorno 🧷

Ahora llega el cambio grande

Simulamos lo que haría una herramienta de IA: reescribe el script, agrega un archivo y toca los datos.

printf 'import csv\n\ndef total_por_ciudad(ruta):\n    with open(ruta) as f:\n        filas = list(csv.DictReader(f))\n    return {f["ciudad"]: int(f["monto"]) for f in filas}\n' > reporte.py
printf 'canal,monto\nBodegas,4200\n' > canales.csv
printf 'Cusco,760\n' >> ventas.csv
git status --short
 M reporte.py
 M ventas.csv
?? canales.csv

Tres archivos tocados. Sin el commit de antes, esto sería un montón; con él, es una lista de cosas que puedes revisar una por una 📋

Mirar exactamente qué hizo

git diff --stat
git diff ventas.csv
 reporte.py | 5 ++++-
 ventas.csv | 1 +
 2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/ventas.csv b/ventas.csv
index 0c80877..7a40551 100644
--- a/ventas.csv
+++ b/ventas.csv
@@ -1,3 +1,4 @@
 ciudad,monto
 Lima,1200
 Arequipa,890
+Cusco,760

Ese diff es la herramienta más importante de todo el capítulo. No estás confiando ni desconfiando: estás mirando 👀

Aceptar una parte y rechazar otra

Aquí es donde se paga el capítulo 4. No hace falta aceptar todo o nada:

git add reporte.py canales.csv
git status --short
git restore ventas.csv
git status --short
cat ventas.csv
A  canales.csv
M  reporte.py
 M ventas.csv
A  canales.csv
M  reporte.py
ciudad,monto
Lima,1200
Arequipa,890

El código nuevo se queda, el cambio en los datos se fue. Cusco desapareció y el resto sigue 🎯

git commit -q -m "El reporte calcula el total por ciudad

Escrito con ayuda de una herramienta de IA y revisado antes de entrar."
git log --oneline
git status --short
5be5731 El reporte calcula el total por ciudad
feb5519 Primera version del reporte de ventas

Deshacerlo entero

Y si el cambio no sirve, vuelves al punto de antes sin pensar:

printf 'algo que la IA propuso y no sirve\n' > reporte.py
printf 'basura.txt\n' > basura.txt
git status --short
git restore .
git clean -qfd
git status --short
head -3 reporte.py
 M reporte.py
?? basura.txt
import csv

def total_por_ciudad(ruta):

restore . devuelve lo que Git conocía y clean -fd se lleva lo que no conocía. Los dos juntos son "vuelve a como estaba" 🔙

Tres reglas que uso

  1. Commit antes de pedir. Siempre, aunque el mensaje diga "antes de tocar nada".
  2. Revisar el diff antes de aceptar. Quien firma el commit eres tú, y en una revisión de equipo vas a tener que explicarlo.
  3. Ramas para lo experimental. Si vas a probar algo grande, una rama de 10 y tu main se queda intacta.

Y una cosa sobre qué le das

Las herramientas de IA leen tu carpeta. Si ahí dentro hay un .env con claves o un CSV con datos de clientes, eso puede terminar saliendo de tu máquina 🔐

El .gitignore del capítulo 9 no basta aquí, porque muchas herramientas leen archivos ignorados igual. Lo que sirve es no tener secretos sueltos en la carpeta del proyecto, y trabajar con datos de ejemplo cuando los de verdad son de un cliente.

La trampa

Le pides a una herramienta de IA que reorganice el proyecto entero. Acepta todos los cambios de una y prueba.

$ git status --short
 M reporte.py
 M ventas.csv
 M canales.csv
 D total.py
 M README.md
?? utils/

# y ahora nada funciona. que cambio exactamente?
Qué está mal

Seis archivos tocados y ningún punto de retorno 😵

Cuando el cambio lo escribes tú, vas viendo. Cuando lo escribe una IA, llega todo junto y en un minuto, y si no funcionaba desde antes ya no sabes qué parte lo rompió.

Lo que convierte eso en algo manejable es un commit antes de pedirle nada. Con eso, git diff te muestra exactamente lo que hizo y git restore te devuelve el estado anterior entero.

Es la costumbre más barata que conozco: diez segundos de commit para poder aceptar cambios grandes sin miedo.

Comprueba que se entendió

Comprueba que lo tienes

Vas a pedirle a una IA que reorganice tu proyecto. ¿Qué haces antes?

  • Un commit, aunque sea con mensaje de "antes de tocar"
  • Una copia de la carpeta en el escritorio
  • Nada, si sale mal deshago con el editor
  • Subo el proyecto a GitHub

Ejercicios

1. Deja el punto de retorno

Crea el proyecto del catálogo y guárdalo antes de pedir nada.

cd ..
mkdir catalogo
cd catalogo
git init -q
printf 'bodega,ciudad\nBodega Inti,Cusco\n' > bodegas.csv
printf 'import csv\n' > reporte.py
git add .
git commit -q -m "Primera version del catalogo de bodegas"
git status --short
echo "punto de retorno listo"
punto de retorno listo

Con eso ya puedes aceptar cambios grandes sin miedo.

2. Simula el cambio grande

Tres archivos tocados de golpe.

printf 'import csv\n\ndef bodegas_por_ciudad(ruta):\n    pass\n' > reporte.py
printf 'canal,monto\nBodegas,4200\n' > canales.csv
printf 'Minimarket Sol,Trujillo\n' >> bodegas.csv
git status --short
 M bodegas.csv
 M reporte.py
?? canales.csv

Dos modificados y uno nuevo.

3. Mira qué cambió de verdad

El resumen y después el detalle de los datos.

git diff --stat
git diff bodegas.csv
 bodegas.csv | 1 +
 reporte.py  | 3 +++
 2 files changed, 4 insertions(+)
diff --git a/bodegas.csv b/bodegas.csv
index 9fe9605..d3027d2 100644
--- a/bodegas.csv
+++ b/bodegas.csv
@@ -1,2 +1,3 @@
 bodega,ciudad
 Bodega Inti,Cusco
+Minimarket Sol,Trujillo

Una línea agregada al CSV. Ahora sí puedes decidir 👀

4. Acepta una parte

Quédate con el código y descarta el cambio en los datos.

git add reporte.py canales.csv
git restore bodegas.csv
git status --short
cat bodegas.csv
A  canales.csv
M  reporte.py
bodega,ciudad
Bodega Inti,Cusco

El minimarket se fue y el código nuevo se queda 🎯

5. Guárdalo diciendo cómo se hizo

El cuerpo del commit es buen sitio para dejarlo dicho.

git commit -q -m "El reporte agrupa las bodegas por ciudad

Escrito con ayuda de una herramienta de IA y revisado antes de entrar."
git log -1 --format="%s%n%n%b"
El reporte agrupa las bodegas por ciudad

Escrito con ayuda de una herramienta de IA y revisado antes de entrar.

Dentro de un año, esa línea explica por qué el estilo del archivo cambió.

6. Deshaz un cambio entero

Vuelve al punto anterior, incluidos los archivos que no conocía.

printf 'propuesta que no sirve\n' > reporte.py
printf 'temporal\n' > borrame.txt
git status --short
git restore .
git clean -qfd
git status --short
cat reporte.py
 M reporte.py
?? borrame.txt
import csv

def bodegas_por_ciudad(ruta):
    pass

restore para lo conocido, clean para lo nuevo 🔙

7. Pide el diff de un archivo que no existe

Comprueba qué pasa cuando el nombre está mal escrito.

git diff bodegas-2019.csv
fatal: ambiguous argument 'bodegas-2019.csv': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Git no compara contra nada inventado, y ese error es la señal de que te equivocaste de nombre 🛑

Lo que te llevas

Commit antes de pedir, diff antes de aceptar. Quien firma el commit eres tú.

¿Tienes alguna duda o consulta?