Tres sitios, no uno
En el capítulo 3 dije que señalar y guardar eran dos pasos. Ahora te cuento por qué, porque de aquí salen casi todos los enredos del principio.
Un archivo tuyo puede estar en tres sitios a la vez, y con distinto contenido en cada uno:
- La carpeta. Lo que ves cuando abres el archivo. Aquí editas.
- La foto. Lo que se guardará en el próximo commit. Aquí
entra con
git add. - La historia. Lo que ya quedó guardado. Aquí entra con
git commit.
Se ve clarísimo haciéndolo. Armo el repositorio de ventas:
mkdir tienda cd tienda git init -q printf 'ciudad,monto\nLima,1200\n' > ventas.csv git add ventas.csv git commit -q -m "Ventas de Lima" git status --short
Sin salida, porque los tres sitios dicen lo mismo. Ahora los separo a propósito: edito el archivo y saco la foto, y después vuelvo a editarlo.
printf 'Arequipa,890\n' >> ventas.csv git add ventas.csv printf 'Trujillo,1450\n' >> ventas.csv git status
On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: ventas.csv Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: ventas.csv
Ahí está lo importante: el mismo archivo aparece dos veces. Una en Changes to be committed, que es la foto con Arequipa, y otra en Changes not staged, que es lo de Trujillo esperando en la carpeta.
Preguntar qué hay en cada sitio
git diff a secas compara la carpeta contra la foto. O sea, te
dice qué te falta agregar:
git diff
diff --git a/ventas.csv b/ventas.csv index 0c80877..2961128 100644 --- a/ventas.csv +++ b/ventas.csv @@ -1,3 +1,4 @@ ciudad,monto Lima,1200 Arequipa,890 +Trujillo,1450
Y con --staged compara la foto contra la historia. Te dice qué
entraría si hicieras commit ahora mismo:
git diff --staged
diff --git a/ventas.csv b/ventas.csv index b5256c1..0c80877 100644 --- a/ventas.csv +++ b/ventas.csv @@ -1,2 +1,3 @@ ciudad,monto Lima,1200 +Arequipa,890
Dos comandos casi iguales que contestan preguntas distintas. Yo los uso así:
el primero antes del add, el segundo antes del commit 🔍
Sacar algo de la foto
Agregaste un archivo que no querías. Se quita de la foto sin perder nada de lo que escribiste:
git restore --staged ventas.csv git status --short
M ventas.csv
La M pasó de la primera columna a la segunda. La primera columna
es la foto, la segunda es la carpeta. Con eso lees el estado corto de un
vistazo y ya no vuelves a mirar el largo.
El error de restaurar lo que no existe
git restore --staged clientes.csv
error: pathspec 'clientes.csv' did not match any file(s) known to git
Ese known to git es la clave: no es que el archivo no exista, es que Git no lo conoce. Un archivo que nunca entró a un commit ni a una foto es invisible para casi todos los comandos.
La trampa
Arreglas un precio mal puesto en el CSV de ventas, haces el add y antes de guardar te das cuenta de que había otro error y lo corriges también. Commit y a otra cosa.
$ git add ventas.csv # aquí el archivo tenía UN arreglo $ nano ventas.csv # y aquí le hiciste el segundo $ git commit -m "Se corrigen los precios de Lima" [main 3c1f80a] Se corrigen los precios de Lima 1 file changed, 1 insertion(+), 1 deletion(-)
Qué está mal
El segundo arreglo no entró 😬
Lo que se guarda no es el archivo que tienes delante, es la foto que sacaste con el add. Todo lo que edites después de esa foto se queda esperando en la carpeta.
Y el commit no miente ni avisa: dice una inserción y una eliminación, que es exactamente lo que había en la foto. Por eso el número de líneas del resumen es de lo más útil que imprime git, y por eso conviene mirarlo.
La costumbre que lo evita es git status antes de cada commit. Si un archivo aparece a la vez en Changes to be committed y en Changes not staged, es justo esto.
Comprueba que se entendió
Comprueba que lo tienes
Haces git add ventas.csv, después editas el archivo otra vez y haces commit. ¿Qué se guardó?
- Todo lo que hay en el archivo ahora mismo
- Solo lo que había cuando hiciste el
add - Nada, porque el archivo cambió después
- Git avisa y no deja hacer el commit
Ejercicios
1. Deja el archivo en los dos sitios a la vez
Agrega el canal bodega a una ciudad, saca la foto, y después agrega otra ciudad sin sacar foto. Mira el estado corto.
printf 'Cusco,760\n' >> ventas.csv git add ventas.csv printf 'Piura,540\n' >> ventas.csv git status --short
MM ventas.csv
Dos letras M en la misma línea: la primera es la foto, la
segunda la carpeta. El archivo está en los dos sitios con contenido distinto.
2. Pregunta qué falta por agregar
Muestra solo lo que está en la carpeta y todavía no en la foto.
git diff --stat
ventas.csv | 1 + 1 file changed, 1 insertion(+)
El --stat resume en vez de mostrar línea por línea. Cuando el
cambio es grande es lo primero que quieres ver.
3. Y qué entraría si guardaras ahora
Lo mismo pero comparando la foto contra la historia.
git diff --staged --stat
ventas.csv | 3 +++ 1 file changed, 3 insertions(+)
Este es el que yo miro siempre antes de un commit. Si el número de líneas no es el que esperabas, algo se coló.
4. Guarda solo lo que está en la foto
Haz el commit y comprueba que Piura se quedó fuera.
git commit -q -m "Entra Cusco en las ventas"
git status --short
M ventas.csv
Piura sigue ahí esperando, con su M en la segunda columna. No se
perdió, simplemente no era parte de esa foto 🙂
5. Mira qué versión quedó guardada
Pide el archivo tal como está en el último commit y compáralo con el de tu carpeta.
git show HEAD:ventas.csv
echo "--- y en la carpeta ---"
cat ventas.csv
ciudad,monto Lima,1200 Arequipa,890 Trujillo,1450 Cusco,760 --- y en la carpeta --- ciudad,monto Lima,1200 Arequipa,890 Trujillo,1450 Cusco,760 Piura,540
Cinco líneas en la historia y seis en la carpeta. Los dos sitios son distintos y los dos son correctos.
6. Tira lo que hay en la carpeta y no está guardado
Descarta el cambio de Piura, que no llegó a ningún commit. Ojo: esto sí borra.
git restore ventas.csv cat ventas.csv git status --short
ciudad,monto Lima,1200 Arequipa,890 Trujillo,1450 Cusco,760
Piura desapareció y el estado quedó limpio. restore sin
--staged pisa la carpeta con lo que hay en la historia, y lo que
no estaba guardado no se recupera 🗑️
7. Un archivo que Git no conoce
Crea un CSV de clientes y trata de restaurarlo sin haberlo agregado nunca. Tiene que fallar.
printf 'bodega,ciudad\nBodega Sol,Lima\n' > clientes.csv
git restore clientes.csv
error: pathspec 'clientes.csv' did not match any file(s) known to git
Restaurar significa traer de vuelta algo guardado, y de este archivo no hay nada guardado. Para Git todavía no existe 👻
Lo que te llevas
El commit guarda la foto que sacaste, no el archivo que tienes delante.