Domina el control de versiones: usa `git status` y `git diff` para inspeccionar el estado del trabajo Git

Domina el control de versiones: usa `git status` y `git diff` para inspeccionar el estado del trabajo

DUGLAS MORENODUGLAS MORENO 👁 1

Introducción

Si te estás iniciando en Git (o si ya lo usás pero querés afianzar los conceptos básicos), dominar dos comandos simples pero poderosos puede marcar la diferencia: git status y git diff. Ambos te permiten ver lo que está pasando en tu repositorio en cada momento, y saber exactamente qué cambios tenés en el directorio de trabajo, cuáles están listos para ser guardados (staged) y cuáles todavía están en el área de trabajo.

Esta guía práctica va paso a paso, con ejemplos de la vida real y la salida exacta que verás en la terminal. No importa si trabajás solo en un pequeño proyecto personal o colaborás en un equipo grande; entender cómo leer git status y git diff te ayudará a evitar commits accidentales, a mantener un historial limpio y a resolver problemas cuando las cosas se complicaran.

Al finalizar, vas a ser capaz de:

  • Interpretar la salida de git status en diferentes escenarios (archivos sin cambios, modificados, nuevos, eliminados, renombrados, etc.).
  • Usar git diff para examinar cambios sin staged y cambios con staged.
  • Aplicar banderas útiles (--porcelain, -s, --cached, etc.) para automatizar tareas o filtrar ruido.
  • Evitar errores comunes, como cometer cambios no deseados o olvidar archivos importantes que deberían estar en .gitignore.

Así que tomá una taza de café, abrí una terminal y comenzá a explorar cómo Git te da visibilidad total sobre tu código.


Por qué estos comandos son fundamentales

Git funciona sobre un flujo de trabajo basado en instantáneas: cada commit guarda un momento exacto del árbol de directorios. Lo que hay entre esos momentos son cambios que todavía no han sido fijados en una nueva instantánea. git status es el indicador de tráfico que te avisa qué cambios hay, mientras que git diff es la lupa que te permite inspeccionarlos.

Sin esta visibilidad, podrías:

  • Agregar accidentalmente archivos con contenido de depuración o credentials a tu próximo commit.
  • Pensar que un cambio ya está listo para el commit cuando todavía está solo en el área de trabajo.
  • Perderte al intentar deshacer un cambio que necesitás de vuelta.
  • Enfrentar conflictos al fusionar ramas sin darte cuenta de que tenías cambios locales no stageados.

Al dominar estos dos comandos, te asegurás de que siempre sepas lo que estás a punto de comprometer, lo cual es especialmente crítico en equipos donde cada miembro debe estar alineado sobre qué forma del código está siendo versionada.


El flujo de trabajo básico de Git explicado

Antes de bucear en los comandos, repasemos el concepto mental que Git usa:

  1. Directorio de trabajo – La carpeta en tu disco donde editás archivos. Esto es donde haces cambios en tiempo real.
  2. Área de staging (índice) – Un área intermedia donde puedes seleccionar qué cambios querés incluir en el próximo commit. Podes tener cambios tanto staged (en el índice) como unstaged (solo en el directorio de trabajo).
  3. Historial de commits – Una cadena inmutable de instantáneas (commits) que representan el estado de los archivos en el momento en que fueron guardados.

Puedes pasar cambios del área de trabajo al área de staging (git add), desde el área de staging al historial (git commit), o directamente entre ellos usando git reset o git checkout. git status te dice dónde se encuentran tus cambios actualmente; git diff te muestra exactamente qué cambios hay en cada una de esas áreas.


git status: el indicador de tráfico de tu repositorio

Ejecutándolo por primera vez

Abre una terminal dentro de cualquier repositorio Git y simplemente escribe:

$ git status

Obtendrás algo como esto (tu salida puede variar ligeramente en color y texto exacto, dependiendo de tu versión de Git y de la configuración):

​$ git status
​En la rama 'main'
​Los siguientes archivos están listos para ser confirmados:
​  (usa "git rm --cached <archivo>..." para eliminarlos de la lista)
​	modificado:   archivo_ejemplo.txt
​
​Los siguientes archivos han sido agregados pero todavía no están en la lista:
​  (usa "git add <archivo>..." para agregarlos al área de staging)
​  nuevo_archivo.py
​
​Los siguientes archivos han sido modificados pero todavía no están en la lista:
​  (usa "git add <archivo>..." para agregarlos al área de staging)
​  config.yaml
​
​Los siguientes archivos han sido eliminados pero todavía no están en la lista:
​  (usa "git rm --cached <archivo>..." para eliminarlos de la lista)
​  registro_antiguo.log
​
​Los siguientes archivos han sido movidos; ¿ainda no están en la lista? (usa "git add <archivo>..." para agregarlos)
​  datos/originales.csv → datos/nuevos.csv

Esta es la vista predeterminada (o verbose) que Git muestra. Desglosémosla sección por sección:

Sección Significado
En la rama 'main' Te indica en qué rama estás actualmente. Saber en qué rama estás ayuda a evitar accidentalmente confirmar cambios en la rama equivocada.
Los siguientes archivos están listos para ser confirmados: Archivos que están staged (es decir, agregados al índice). Aparece un signo de tabulación ( ) antes del nombre, y la palabra modificado: indica que el archivo existe pero su contenido cambió.
Los siguientes archivos han sido agregados pero todavía no están en la lista: Archivos nuevos que Git acaba de detectar (no están bajo control de versiones). La palabra nuevo_archivo.py aparece sin prefijo.
Los siguientes archivos han sido modificados pero todavía no están en la lista: Archivos ya bajo control de versiones, pero con cambios no stageados. El prefijo modificado: señala una diferencia de contenido.
Los siguientes archivos han sido eliminados pero todavía no están en la lista: Archivos eliminados del sistema de archivos pero aún en el índice (es decir, eliminados del historial). El prefijo eliminado: aparece.
Los siguientes archivos han sido movidos; ¿ainda no están en la lista? Git puede detectar renames cuando un archivo es movido dentro del mismo repositorio. El formato antiguo → nuevo indica un movimiento.

Flags útiles para una salida más concisa

Cuando necesitas una salida que sea fácil de analizar en scripts, podés usar --porcelain. Esto elimina el texto descriptivo y deja solo un formato legible por máquina:

$ git status --porcelain
M archivo_ejemplo.txt
?? nuevo_archivo.py
M config.yaml
D  registro_antiguo.log
R  datos/originales.csv datos/nuevos.csv

Códigos:

  • M – modificado (staged)
  • ?? – nuevo sin seguimiento
  • M – modificado (no stageado) cuando está fuera del área de staging (aún aparece como M en la salida normal)
  • D – eliminado (no stageado)
  • R – renombrado (detección)

También hay un alias corto -s que hace lo mismo que --porcelain.

$ git status -s
M archivo_ejemplo.txt
?? nuevo_archivo.txt
 M config.yaml
 D  registro_antiguo.log
R  datos/originales.csv datos/nuevos.csv

Ahora los signos de espacio indican si un cambio está staged (M, A, D, R) o no ( M, ??, D).

Interpretando colores y configuraciones

Git puede mostrar colores para ayudarte a diferenciar rápidamente entre staged y unstaged. El esquema de colores predeterminado es:

  • Verde – cambios listos para ser confirmados (staged).
  • Rojo/Naranja – cambios sin stagear.
  • Amarillo/Aqua – archivos nuevos o eliminados.

Si tu terminal no muestra colores, podrías tener color.status desactivado en tu configuración de Git. Podés reactivarlo con:

$ git config --global color.status auto

O forzar el uso de colores globalmente:

$ git config --global color.ui true

Ahora estás listo para una interpretación visual rápida de cada sesión de git status.


git diff: viendo los cambios en detalle

Mientras que git status te dice qué ha cambiado, git diff te muestra cómo ha cambiado. Hay tres variantes primarias que necesitas conocer:

Comando Muestra
git diff Cambios no stageados (diferencia entre el directorio de trabajo y el índice).
git diff --cached (o git diff -c) Cambios staged (diferencia entre el índice y el último commit).
git diff HEAD Lo mismo que git diff (área de trabajo vs HEAD) – útil para comparar con la rama actual.

También podés combinar con referencias como git diff HEAD~1 para comparar con el commit anterior, o git diff branch_name para ver cómo se vería el diff si fusionáramos otra rama.

git diff: cambios sin stagear

Imaginá que editás archivo_ejemplo.txt con un editor de texto. Después de la edición, ejecutás:

$ git diff

La salida te mostrará una unión unificada de diff de una línea con el contexto surrounding:

$ git diff
index 1234567..89abcde 100644
--- a/archivo_ejemplo.txt
+++ b/archivo_ejemplo.txt
@@ -1,5 +1,5 @@
 Este es un archivo de ejemplo.
-La primera línea es antigua.
+La primera línea es nueva.
 El archivo contiene varias líneas.
-La última línea está cambiada.
+La última línea está actualizada.

Explicación:

  • index 1234567..89abcde – identifica los dos hashes de blobs (la versión almacenada en el índice y la versión actual en el directorio de trabajo).
  • --- a/archivo_ejemplo.txt / +++ b/archivo_ejemplo.txt – las rutas de prefijo a/ (antiguo) y b/ (nuevo). El prefijo b/ denota el árbol de trabajo.
  • @@ -1,5 +1,5 @@ – el hunk de diff: comienza en la línea 1, 5 líneas en ambos lados.
  • Las líneas comenzando con - son eliminadas; las líneas comenzando con + son agregadas.

Si tenés múltiples cambios en el mismo archivo, Git agrupará cambios contiguos en hunks para mantener la salida compacta.

git diff --cached (o git diff -c): cambios staged

Ahora agregá esos cambios al área de staging:

$ git add archivo_ejemplo.txt

Ahora ejecutá git diff --cached:

$ git diff --cached
index 89abcde..fedcba 100644
--- a/archivo_ejemplo.txt
+++ b/archivo_ejemplo.txt
@@ -1,5 +1,5 @@
 Este es un archivo de ejemplo.
-La primera línea es antigua.
+La primera línea es nueva.
 El archivo contiene varias líneas.
-La última línea está cambiada.
+La última línea está actualizada.

Observa que la diff es idéntica a la anterior (porque solo había un cambio). Pero este diff representa la diferencia entre el índice (staged) y el commit más reciente. Si tenías cambios tanto en staged como sin stagear, git diff y git diff --cached mostrarán dos conjuntos de cambios separados.

Otros sabores útiles de git diff

  • git diff HEAD – muestra cambios sin stagear contra el commit más reciente (equivalente a git diff cuando no hay cambios staged).

  • git diff HEAD~1 – muestra cambios comparando el commit actual con su padre (útil para revisar el diff de un commit individual).

  • git diff --no-ext-diff – fuerza el uso del diff integrado en lugar de programas externos como diff.

  • git diff --word-diff – muestra cambios en términos de palabras en lugar de líneas, útil para diffs pequeños.

  • git diff --stat – da un resumen rápido de cuántos archivos cambiaron y cuántas líneas, por ejemplo:

    $ git diff --stat
    2 archivos cambiados, 5 inserciones (+), 3 eliminaciones (-)

Estas banderas pueden combinarse; por ejemplo, git diff --cached --stat te da un conteo rápido de cambios staged.


Escenarios paso a paso: comandos y salidas esperadas

A continuación, exploraremos escenarios realistas y mostraremos exactamente qué verás en la terminal después de cada comando. Este enfoque práctico te ayudará a reconocer los patrones.

Escenario 1: Repositorio limpio (sin cambios)

Empezamos con un repositorio recién inicializado que ya tiene algunos commits. Ejecutamos git status:

$ git status
En la rama 'main'

Todo limpio

No hay secciones de archivos. La frase "Todo limpio" indica que el área de trabajo, el área de staging y HEAD están sincronizados.

Escenario 2: Modificar un archivo sin staging

Editá README.md agregando una nueva línea al principio. Luego ejecutá git status:

$ git status
En la rama 'main'

Los siguientes archivos han sido modificados pero todavía no están en la lista:
  (usa "git add <archivo>..." para agregarlos al área de staging)
	README.md

Ahora podés ver el diff:

$ git diff
index 9f7b2c1..3e8a4d5 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,11 @@
 # Mi Proyecto
 
-Esto es el contenido original.
+Esto es el contenido original.
+Linea agregada por el desarrollador.
 El proyecto está en desarrollo activo.

El - muestra la línea eliminada (originalmente no había nada allí), y + muestra la línea agregada.

Escenario 3: Agregar un nuevo archivo sin staging

Creá un nuevo archivo script.sh con alguna lógica. Ejecutá git status:

$ git status
En la rama 'main'

Los siguientes archivos han sido agregados pero todavía no están en la lista:
  (usa "git add <archivo>..." para agregarlos al área de staging)
	script.sh

git diff no mostrará nada para archivos nuevos porque no hay diff previo; podés inspeccionar el contenido con git diff --cached (no tiene staged aún) o git show --stat. Para ver el diff contra la versión no existiente, podés usar git diff --no-index /dev/null script.sh, pero normalmente solo querés agregar el archivo.

Escenario 4: Eliminar un archivo sin staging

Borrá registro_antiguo.log. Luego ejecutá git status:

$ git status
En la rama 'main'

Los siguientes archivos han sido eliminados pero todavía no están en la lista:
  (usa "git rm --cached <archivo>..." para eliminarlos de la lista)
	registro_antiguo.log

Para ver la diff de eliminación (área de trabajo vs HEAD), podés usar:

$ git diff
index 9f7b2c1..0000000 100644
--- a/registro_antiguo.log
+++ b/registro_antiguo.log
@@ -1,3 +0,0 @@
 linea 1
 linea 2
 linea 3

El diff muestra todas las líneas eliminadas. Si quieres stagear la eliminación (para que sea parte del próximo commit), usá git add registro_antiguo.log (o git rm registro_antiguo.log).

Escenario 5: Agregar un archivo al área de staging

Ahora stageá script.sh:

$ git add script.sh

Ejecutá git status nuevamente:

$ git status
En la rama 'main'

Los siguientes archivos están listos para ser confirmados:
  (usa "git rm --cached <archivo>..." para eliminarlos de la lista)
	nuevo_script.sh

Los siguientes archivos han sido agregados pero todavía no están en la lista:
  (usa "git add <archivo>..." para agregarlos al área de staging)
	nuevo_script.sh

Nota cómo nuevo_script.sh aparece tanto en la sección "listos para ser confirmados" como en la sección "agregados pero todavía no están en la lista". Esto parece confuso, pero en realidad es porque el nombre del archivo fue renombrado internamente: Git lo detectó como un nuevo archivo, y también lo stageó. La visualización puede variar ligeramente dependiendo de la versión y configuración de Git. Si querés una visualización más clara, podés desactivar los mensajes de rename usando git config --global status.showRenameInfo false.

Ahora git diff --cached mostrará los cambios que se van a commitear (el contenido completo del archivo en este caso, ya que es nuevo):

$ git diff --cached
index 0000000..a1b2c3d 100644
--- /dev/null
+++ b/nuevo_script.sh
@@ -0,0 +1,9 @@
 #!/bin/bash
 echo "Hola, mundo"
 # Un comentario simple

El diff usa /dev/null como antiguo porque el archivo no existía antes.

Escenario 6: Modificar un archivo y cambiar su estado de staging

Editá README.md nuevamente, y luego stageá el cambio. Después de git add README.md, ejecutá git status:

$ git status
En la rama 'main'

Los siguientes archivos están listos para ser confirmados:
  (usa "git rm --cached <archivo>..." para eliminarlos de la lista)
	README.md

Ahora git diff --cached mostrará solo el diff más reciente (el segundo cambio) porque el diff previo ya está en el commit. git diff mostrará un diff separado si hay cambios adicionales sin stagear.

Escenario 7: Colisiones y conflictos (cuando mergeas)

Imaginá que tenés una rama feature con cambios en archivo_común.txt. Intentás fusionarla a main usando git merge feature. Si archivo_común.txt también tiene cambios no stageados en main, Git reportará un conflicto:

$ git merge feature
Auto-merging archivo_común.txt
CONFLICTO (contenido): Conflicto al fusionar.
Abortando la fusión.

Puedes usar git status para ver el conflicto resaltado:

$ git status
En la rama 'main'

Los siguientes archivos tienen conflictos que deben ser resueltos:
  (usa "git add <archivo>..." para marcarlos como resueltos)
	archivo_común.txt

Ahora git diff mostrará marcas especiales <<<<<<<, =======, >>>>>>> dentro del archivo, mostrando las versiones en conflicto. Una vez que edites el archivo y lo resolvás, podés ejecutar git add archivo_común.txt para continuar con la fusión.


Buenas prácticas y errores comunes

1. Aprovechá --porcelain para scripts

Si estás escribiendo un script de CI/CD que necesita detectar cambios rápidamente, git status --porcelain da una salida limpia y parseable:

#!/bin/bash
# Detectar cambios no stageados
while IFS= read -r linea; do
  caso "${linea:0:2}" in
    " M")
      echo "Archivo modificado sin stagear: ${linea:3}" ;;
    " A")
      echo "Nuevo archivo stageado: ${linea:3}" ;;
    "??")
      echo "Nuevo archivo sin seguimiento: ${linea:3}" ;;
  esac
done < <(git status --porcelain)

Esto te ayuda a automatizar el stageo o el reporte de cambios sin necesidad de lidiar con el texto descriptivo.

2. Evitá commits de archivos grandes o binarios

git diff mostrará diffs binarios que son esencialmente una visión de textura de las diferencias, lo cual puede ser huge. Para activos binarios como imágenes o archivos compilados, debería haber una entrada en .gitignore o deberían ser almacenados en un registro separado. Si accidentalmente ves cambios binarios, git diff --textconv puede intentar mostrarlos como texto.

3. Mantené .gitignore actualizado

El comando git status mostrará archivos nuevos que coinciden con las reglas de .gitignore como ??. Por ejemplo, si agregás *.log a .gitignore y luego creás debug.log, Git lo marcará como "sin seguimiento", pero no lo incluirá en el próximo commit a menos que lo agregues explícitamente. Esto es bueno para mantener limpio el historial.

4. Uso de git reset para revertir cambios no deseados

Si ves un cambio en git diff que no querés commitear, podés:

  • Sacarlo del área de staging sin modificar el archivo: git reset HEAD <archivo>.
  • Desechar los cambios del área de trabajo (perder las ediciones): git checkout -- <archivo>.
  • Deshacer ambas cosas (si estás en un commit limpio): git reset --hard HEAD~1 (cuidado, esto es destructivo).

5. Comprender que git diff solo muestra diferencias a nivel de línea, no de contenido

Si estás buscando cambios sutiles (por ejemplo, un espacio extra), git diff mostrará la línea con un \ y el cambio. Podés usar git diff --ignore-all-space para ignorar los espacios en blanco si están presentes. Para una comparación más detallada, git diff --word-diff mostrará las palabras cambiadas.

6. Uso de git diff para revisar commits anteriores

Cuando necesités verificar exactamente lo que un commit anterior hizo, git show <hash> mostrará tanto el commit metadata como el diff. También puedes hacer git diff <hash>^ <hash> para obtener el diff entre dos commits.

7. Evitá "difs sucios" en ramas compartidas

Si trabajas en una rama que va a ser fusionada (por ejemplo, develop), es buena práctica asegurar que git status sea limpio antes de empezar a mergear. Si hay cambios sin stagear, puedes temporariamente moverlos a un branch de características o guardarlos con git stash:

$ git stash
$ git status

Luego, después de terminar con el merge, podés recuperarlos con git stash pop.

8. Colores y configuración para una mejor visibilidad

Podés personalizar el color de git status por rama usando git config color.status always. Para las diffs, git config --global diff.color.diff auto (o true) asegurará resaltados para git diff.

9. Evitá depender demasiado de git status para la precisión

Aunque git status es una excelente señal de tráfico, no es infalible. Si eliminaste un archivo pero luego lo recuperaste manualmente, git status podría mostrarlo como eliminado. Siempre vale la pena revisar con git diff y git ls-files para estar seguro.

10. Usa git ls-files --others --exclude-standard para detectar archivos no rastreados

A veces git status oculta archivos nuevos que son ignorados por .gitignore. Para una detección completa, podés ejecutar:

$ git ls-files --others --exclude-standard

Esto enumerará todos los archivos no rastreados que Git normalmente omitiría.


Resumen rápido de comandos

Objetivo Comando Salida típica
Ver estado general git status Resumen legible por humanos con colores
Formato parseable git status --porcelain / -s Códigos de dos caracteres (M, A, D, ??, etc.)
Diff de cambios sin stagear git diff Unión unificada de diff (líneas eliminadas/agregadas)
Diff de cambios staged git diff --cached o git diff -c Igual que git diff pero contra el índice
Diff contra último commit git diff HEAD Igual que git diff (si no hay staged)
Diff con un commit anterior git diff HEAD~1 Diff del commit padre
Ver diff en resumen git diff --stat Resumen de conteo de archivos y líneas
Nuevo archivo para staging git add <archivo> Aparece en la sección de staged de git status
Deshacer staging de un archivo git reset HEAD <archivo> El archivo aparece en la sección sin stagear
Descartar cambios en el área de trabajo git checkout -- <archivo> El archivo vuelve a su estado anterior
Guardar cambios temporalmente git stash Las ediciones son eliminadas del área de trabajo, lista para pop
Recuperar cambios almacenados git stash pop o git stash apply Las ediciones son restauradas
Listar archivos no rastreados git ls-files --others --exclude-standard Nombres de archivos que Git ignora normalmente
Mostrar diff de un commit git show <hash> Diff completo con metadata del commit

Conclusión

Git es una herramienta de poderosísima que funciona mejor cuando entendés su flujo de trabajo interno: el área de trabajo (tu edición en tiempo real) → el área de staging (lo que estás a punto de confirmar) → el historial de commits (tu línea de tiempo inmutable). git status y git diff son las dos ventanas que te dan visibilidad sobre cada uno de esos pasos.

Al leer git status, sabrás qué archivos han sido modificados, cuáles son nuevos, cuáles han sido eliminados, o si ha habido renames. Usando --porcelain o -s, puedes adaptar la salida para scripts, mientras que el modo coloreado hace que la inspección visual sea rápida.

git diff te da el poder de ver exactamente cómo se ven esos cambios, ya sea que estén en el área de trabajo (sin stagear) o en el área de staging (listos para el commit). Dominar banderas como --cached, HEAD~1, --stat y --word-diff te da flexibilidad para revisar commits antiguos, verificar cambios pequeños o generar diffs compactos para revisión.

Con los escenarios paso a paso que cubrimos, deberías sentirte cómodo enfrentando casos típicos: repositorios limpios, archivos sin stagear, nuevos archivos, eliminados, renames, conflictos y más. Al aplicar las buenas prácticas (mantener .gitignore actualizado, usar git stash cuando sea necesario, aprovechar los formatos parseables), evitarás muchos errores comunes que pueden causar diffs sucios o commits no deseados.

Finalmente, recuerda que la visibilidad es clave para un flujo de trabajo de versionado saludable. Si alguna vez estás dudando sobre lo que estás a punto de commitear, simplemente ejecuta:

$ git status
$ git diff --cached

Para asegurarte de que estás comprometido con exactamente lo que querés. Con estos dos comandos bajo tu cinturón, estás listo para navegar cualquier cambio en tu código base con confianza y precisión.


¡Feliz coding y que tus repositorios siempre estén limpios!

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario