Guía

git log, diff, show y blame: cómo leer el historial de un proyecto en Git

Actualizado: · Skillaria.Top

git log muestra la lista de commits y permite filtrarlos por autor, fecha, archivo y texto; git diff compara la carpeta de trabajo, el índice y cualquier commit; git show muestra un commit completo; git blame indica qué commit modificó por última vez cada línea de un archivo.

Cuatro comandos resuelven casi todas las preguntas sobre el historial de un proyecto. git log responde a «qué ha pasado», git diff a «qué ha cambiado exactamente», git show a «qué hay dentro de un commit concreto» y git blame a «quién escribió esta línea y cuándo». A continuación tienes técnicas prácticas para cada uno, con las opciones que de verdad se usan en el desarrollo diario.

git log: la lista de commits

Sin argumentos, git log muestra los commits de la rama actual del más reciente al más antiguo: hash SHA-1 completo, autor, fecha y mensaje. Se recorre en un paginador (normalmente less): espacio para la página siguiente, /texto para buscar y q para salir.

commit 7be41d0c9a2e4f1b8d6c3e5a7f9b0c2d4e6f8a1b
Author: Anna Petrova <anna@example.com>
Date:   Mon Oct 5 14:22:10 2026 +0300

    feat: caché de respuestas de la API

No hace falta copiar el hash entero: Git entiende cualquier prefijo único de al menos 4 caracteres, y en la práctica bastan 7.

Salida compacta: --oneline

git log --oneline -10
# 7be41d0 (HEAD -> main, origin/main) feat: caché de respuestas de la API
# 1c02e8f fix: timeout de las peticiones
# 9a4b3c2 refactor: cliente movido a un módulo

La opción -10 (o -n 10) limita el número de commits. Entre paréntesis aparecen los punteros: dónde están HEAD, las ramas locales y remotas y las etiquetas.

Grafo de ramas: git log --graph

Cuando alguien busca «git graph» suele referirse a esto: visualizar ramificaciones y fusiones directamente en la terminal.

git log --oneline --graph --all
# * 3e1f0aa (feature/auth) feat: inicio de sesión con token
# | * 7be41d0 (HEAD -> main) feat: caché de respuestas de la API
# |/
# * 1c02e8f fix: timeout de las peticiones
# *   5d2c7b1 Merge branch 'feature/search'
# |\
# | * 8f3a9e0 feat: búsqueda
# |/
# * 9a4b3c2 refactor: cliente movido a un módulo

--all muestra todas las ramas, no solo la actual. Conviene crear un alias: git config --global alias.lg "log --oneline --graph --all --decorate", y a partir de ahí basta con git lg.

Formato propio: --pretty=format

git log --pretty=format:"%h %ad %an %s" --date=short
# 7be41d0 2026-10-05 Anna Petrova feat: caché de respuestas de la API

Marcadores principales: %h, hash corto; %H, completo; %an, autor; %ae, su e-mail; %ad, fecha de autoría; %ar, fecha relativa («2 days ago»); %s, título del mensaje.

Cómo filtrar el historial con git log

Por autor y fecha

git log --author="Anna"
git log --since="2 weeks ago" --until="2026-10-01"
git log --since=yesterday --oneline

--author acepta una expresión regular y busca en el nombre y en el e-mail. Git entiende las fechas tanto en formato libre como en ISO.

Por el texto del mensaje

git log --grep="fix" -i --oneline

-i hace que la búsqueda no distinga mayúsculas. Si tu equipo pone números de tarea en los mensajes, así encuentras rápido todos los commits de una tarea.

Por archivo o carpeta

git log --oneline -- src/api/client.py
git log --follow -p -- src/api/client.py

El doble guion separa las rutas de las ramas. --follow sigue el historial del archivo a través de los renombrados (funciona con un solo archivo) y -p muestra el parche de cada commit.

Por el código modificado: la búsqueda «pico»

git log -S "retry_count" --oneline     # commits en los que cambió el número de apariciones de la cadena
git log -G "timeout\s*=" --oneline    # commits cuyo diff contiene líneas que casan con la regex

-S encuentra el commit en el que se añadió o se eliminó una función o variable: imprescindible cuando quieres saber adónde fue a parar un trozo de código.

Rangos de commits

git log main..feature      # lo que está en feature pero no en main
git log origin/main..HEAD  # mis commits locales aún sin enviar
git log --no-merges        # sin commits de merge
git log --stat             # qué archivos y cuántas líneas cambiaron

git diff: qué ha cambiado exactamente

Lo principal que hay que entender de git diff es qué dos estados compara. Confundirlos es lo que lleva a preguntar «¿por qué el diff está vacío si lo he cambiado todo?».

ComandoQué compara
git diffcarpeta de trabajo frente al índice (cambios no preparados)
git diff --staged (--cached)índice frente al último commit (lo que entrará en el commit)
git diff HEADcarpeta de trabajo frente al último commit (todo junto)
git diff A Bdos commits, ramas o etiquetas
git diff A...Blos cambios de B desde que se separó de A

Si ya hiciste git add, el git diff normal quedará vacío: los cambios están en el índice, mira --staged. Los archivos nuevos que nunca se han añadido no aparecen en el diff en absoluto.

Cómo leer la salida de diff

diff --git a/config.py b/config.py
index 3b18e51..a1c4f02 100644
--- a/config.py
+++ b/config.py
@@ -10,7 +10,7 @@ DEFAULTS = {
     "host": "localhost",
-    "timeout": 5,
+    "timeout": 30,
     "retries": 3,

Las líneas con - se han eliminado, las de + se han añadido y el resto es contexto. La cabecera @@ -10,7 +10,7 @@ significa que el fragmento empieza en la línea 10 y ocupa 7 líneas en la versión antigua y en la nueva.

Opciones útiles de git diff

git diff --stat main feature      # resumen por archivos
git diff --name-only HEAD~3       # solo los nombres de los archivos cambiados
git diff --word-diff               # cambios por palabras, cómodo para textos
git diff -w                        # ignorar cambios de espacios
git diff main feature -- src/      # limitar a una carpeta

Antes de cada commit conviene mirar git diff --staged: es la última oportunidad de ver un print de depuración o un archivo añadido por error.

git show: un commit completo

git show muestra los metadatos del commit y su diff respecto al padre. Sin argumentos, el último commit.

git show 7be41d0
git show HEAD~2 --stat           # sin parche, solo el resumen
git show v1.2.0                  # etiqueta: anotación y commit
git show main:src/config.py      # el archivo tal como estaba en el commit

La última forma, <revisión>:<ruta>, es especialmente útil: permite ver una versión antigua de un archivo sin cambiar a ella. Redirige la salida a un archivo y recuperarás contenido borrado sin hacer checkout.

git blame: quién cambió esta línea

git blame archivo muestra para cada línea el último commit que la modificó, el autor y la fecha. El nombre suena acusador («blame» es culpar), pero en realidad es una herramienta para encontrar contexto: localizar el commit, leer el mensaje y entender por qué se hizo así.

git blame -L 40,60 src/api/client.py
# 1c02e8f3 (Anna Petrova 2026-09-28 11:04:51 +0300 41)     timeout = settings.timeout
# 9a4b3c2e (Ivan Smirnov 2026-09-14 18:30:02 +0300 42)     session = build_session()
  • -L 40,60: solo un rango de líneas; también vale -L :nombre_funcion.
  • -w: ignorar cambios de espacios para no caer en commits de formato.
  • -C: seguir líneas movidas desde otros archivos.
  • --ignore-rev <hash> o el archivo .git-blame-ignore-revs: saltarse commits masivos como el autoformateo.

El flujo típico de investigación: git blame encuentra el commit, git show lo muestra entero y git log sobre el archivo da los cambios cercanos.

Moverse por el pasado: HEAD~ y HEAD^

Los commits no solo se referencian por hash. HEAD~1 es el padre del commit actual y HEAD~3, el bisabuelo. HEAD^2 es el segundo padre de un commit de merge. También funcionan los nombres de ramas, etiquetas y ramas remotas: origin/main~2. Puedes ver el proyecto completo en un commit antiguo con git switch --detach <hash> y volver con git switch -.

Un historial bueno y uno malo

Todos estos comandos son útiles en la medida en que el historial tenga sentido. Mensajes como «fix», «wip» o «más cambios» vuelven inútiles git log --grep y git blame. Un buen commit es un único cambio lógico con un título que explica qué y por qué: fix: timeout de la API subido a 30 s por la lentitud de la pasarela. Dentro de seis meses, blame encontrará precisamente ese commit y te ahorrará una hora.

Práctica: investigar un bug a través del historial

Supón que tras la última release las peticiones a la API empiezan a fallar por timeout. Así es como la combinación de comandos te lleva a la causa en un par de minutos.

  1. Vemos qué entró en la release: git log v1.4.0..v1.5.0 --oneline. La lista es corta, pero por los títulos el culpable no es evidente.
  2. Acotamos por archivo: git log v1.4.0..v1.5.0 --oneline -- src/api/. Quedan dos commits.
  3. Buscamos en el código: git log -S "timeout" --oneline -- src/api/ encuentra el commit en el que cambió el valor del timeout.
  4. Lo vemos entero: git show 1c02e8f. En el diff se ve que el timeout bajó de 30 a 5 segundos, y el mensaje lo explica: «acelerar la respuesta de la UI».
  5. Comprobamos quién más tocó esa línea: git blame -L :build_session src/api/client.py.

A partir de ahí la solución ya es de ingeniería: restaurar el valor, mover el timeout a la configuración o deshacer el commit con git revert. Y si hay cientos de commits y no se puede encontrar al culpable a ojo, entra en juego git bisect: una búsqueda binaria en el historial que en pocos pasos señala el commit que rompió el comportamiento.

Ajustes que facilitan la vida

git config --global log.date iso            # formato de fechas en log
git config --global diff.colorMoved zebra   # resaltar líneas movidas en diff
git config --global core.pager "less -FRX"  # no abrir el paginador si la salida es corta

Si necesitas procesar la salida con un script, desactiva los colores y el paginador: git --no-pager log --format="%H %s" --no-color. Para procesamiento automático usa el hash completo %H: con el tiempo, los prefijos cortos pueden volverse ambiguos en un repositorio grande.

Resumen

git log con los filtros --oneline, --graph, --author, -S y rutas responde a «qué ha pasado». git diff compara la carpeta de trabajo, el índice y los commits; lo importante es recordar qué compara por defecto. git show despliega un commit o una versión antigua de un archivo, y git blame te lleva de una línea de código a la decisión que la originó. La lectura del historial y la navegación por los commits se practican en el curso de Git.

Preguntas frecuentes

¿Cómo salgo de git log?

Pulsa q: la salida está abierta en el paginador less. Para imprimir sin paginador usa git --no-pager log o la opción -n con un número pequeño.

¿Cómo veo el historial de un archivo borrado?

Ejecuta git log --oneline -- ruta/al/archivo (con doble guion), y para ver el contenido antes del borrado, git show &lt;hash&gt;^:ruta/al/archivo.

¿Cómo comparo una rama local con la remota?

Primero git fetch y luego git diff origin/main, o git log origin/main..HEAD para ver tus commits sin enviar.

¿Hay alguna forma gráfica de ver el historial?

Sí, Git incluye gitk, y el grafo del historial también está integrado en VS Code, los IDE de JetBrains y las interfaces web de GitHub y GitLab.

¿Por qué git diff no muestra nada?

Lo más probable es que los cambios ya estén en el índice tras git add: mira git diff --staged. Los archivos nuevos sin seguimiento git diff no los muestra en absoluto.

Aprende este tema en vídeo

Este tema se explica a fondo y con práctica en el curso «Git desde cero hasta desarrollador seguro».

Ir al curso