Magia de Recuperación en Git: Reflog, Recuperación de Reset y Cherry-Picking

2025-09-09 | Gabriel Garrido | 9 min de lectura
Share:

Apoya este blog

Si te resulta util este contenido, considera apoyar el blog.

Introducción

En este artículo vamos a explorar las características de recuperación más poderosas de Git que pueden salvarte el día cuando las cosas salen mal. Si alguna vez perdiste commits después de un rebase mal hecho, borraste accidentalmente un branch, o necesitaste agarrar solo un commit específico de otro branch, conocés el pánico. Pero Git nunca olvida realmente - es solo cuestión de saber dónde buscar.


El reflog de Git es como una máquina del tiempo para tu repositorio. Cada acción que hacés se registra, y con los comandos correctos, podés recuperar casi cualquier cosa. También vamos a profundizar en cherry-picking, que te permite extraer quirúrgicamente commits específicos y aplicarlos donde los necesites.


Al final de este artículo, nunca más vas a temer a las operaciones de Git. Vas a saber que pase lo que pase, casi siempre hay una forma de recuperar tu trabajo.


Entendiendo el Reflog

El reflog (registro de referencias) es la red de seguridad de Git. Registra cada cambio en HEAD y las puntas de los branches en tu repositorio local. Pensalo como el historial de deshacer de Git - pero mucho más poderoso.


Empecemos viendo qué hay en tu reflog:

git reflog
# o para más detalle
git reflog show HEAD

Vas a ver algo así:

3f7a8b9 (HEAD -> main) HEAD@{0}: commit: Agregar nueva función
8d4c2e1 HEAD@{1}: rebase -i (finish): returning to refs/heads/main
8d4c2e1 HEAD@{2}: rebase -i (pick): Actualizar documentación
a5b9c3d HEAD@{3}: rebase -i (squash): Arreglar bug
e2f1d4c HEAD@{4}: rebase -i (start): checkout origin/main
7c9e3a2 HEAD@{5}: commit: Trabajo en progreso

Cada entrada muestra:

  • El SHA del commit
  • La referencia de entrada del reflog (HEAD@{n})
  • La acción que se realizó
  • El mensaje del commit o detalles de la operación

¿Lo hermoso? Estas entradas persisten por 90 días por defecto (30 días para commits inalcanzables), dándote mucho tiempo para recuperarte de errores.


Recuperándose de un Rebase Malo

Digamos que estás haciendo rebase y las cosas salen horriblemente mal. Tal vez borraste accidentalmente commits importantes o resolviste conflictos incorrectamente. ¡No entres en pánico!


Escenario: Rebase interactivo arruinado

# Hiciste un rebase interactivo
git rebase -i HEAD~5

# Accidentalmente borraste commits importantes o arruinaste el historial
# Ahora tu branch está roto

Recuperación usando reflog:

# Primero, verificá dónde estabas antes del rebase
git reflog

# Encontrá la entrada antes de "rebase -i (start)"
# Digamos que es HEAD@{5}

# Opción 1: Reset al estado antes del rebase
git reset --hard HEAD@{5}

# Opción 2: Si querés ser más cuidadoso, creá un branch de backup primero
git branch backup-antes-reset
git reset --hard HEAD@{5}

Tip pro: Siempre verificá a qué estás haciendo reset primero:

# Ver qué hay en esa entrada del reflog
git show HEAD@{5}

# Ver el log completo desde ese punto
git log HEAD@{5} --oneline -10

Recuperando Commits Borrados (Después de git reset)

¿Accidentalmente ejecutaste git reset --hard y perdiste commits? No se fueron, solo están sin referencia. Así es como recuperarlos:


Escenario: Reset hard accidental

# Tenías trabajo importante
git log --oneline
# abc123 Función importante
# def456 Bugfix crítico
# ghi789 Trabajo previo

# Luego accidentalmente hiciste reset
git reset --hard HEAD~2

# ¡Oh no! ¡Tu función importante y bugfix se fueron!

Proceso de recuperación:

# Paso 1: Encontrar los commits perdidos en reflog
git reflog
# Vas a ver algo como:
# ghi789 HEAD@{0}: reset: moving to HEAD~2
# abc123 HEAD@{1}: commit: Función importante
# def456 HEAD@{2}: commit: Bugfix crítico

# Paso 2: Recuperar al commit perdido
git reset --hard HEAD@{1}
# o usar el SHA directamente
git reset --hard abc123

# Alternativa: Cherry-pick commits específicos si no querés hacer reset
git cherry-pick abc123
git cherry-pick def456

Creando un branch de recuperación: A veces querés explorar los commits perdidos sin afectar tu branch actual:

# Crear un nuevo branch desde el commit perdido
git branch branch-recuperacion abc123

# Cambiar a él y verificar
git checkout branch-recuperacion
git log --oneline

# Si todo se ve bien, merge de vuelta
git checkout main
git merge branch-recuperacion

Recuperando Branches Eliminados

¿Borraste un branch por error? Mientras no haya sido borrado en el remoto y force-pusheado, podés recuperarlo localmente.


Escenario: Eliminación accidental de branch

# Tenías un feature branch
git branch
# * main
#   feature-increible
#   bugfix-critico

# Accidentalmente lo borraste
git branch -D feature-increible
# Deleted branch feature-increible (was 5a3f8c9).

Métodos de recuperación:

Método 1: Si ves el SHA en el mensaje de eliminación

# Git te dice el SHA al borrar
# Solo recreá el branch desde ese commit
git branch feature-increible 5a3f8c9

# O checkout y recrear
git checkout -b feature-increible 5a3f8c9

Método 2: Usando reflog para encontrar el branch

# Buscar en reflog el nombre del branch
git reflog show --all | grep feature-increible

# O buscar commits de ese branch
git reflog --all

# Una vez que encuentres el último SHA del commit
git checkout -b feature-increible-recuperado <sha>

Método 3: Si recientemente hiciste checkout del branch

# Git rastrea los checkouts de branches
git reflog | grep checkout

# Podrías ver:
# 3d4e5f6 HEAD@{3}: checkout: moving from feature-increible to main

# Encontrá desde dónde te moviste DE feature-increible
git checkout -b feature-increible-recuperado 3d4e5f6

Cherry-Picking: Extracción Quirúrgica de Commits

Cherry-picking te permite tomar commits específicos de un branch y aplicarlos a otro. Es como copiar y pegar commits.


Cherry-pick básico:

# Estás en el branch main y querés un commit específico del branch feature
git checkout main

# Encontrar el commit que querés
git log feature --oneline
# abc123 Agregar función increíble
# def456 Arreglar typo
# ghi789 Actualizar tests

# Cherry-pick el commit específico
git cherry-pick abc123

# El commit ahora está aplicado en main

Cherry-picking múltiples commits:

# Elegir un rango de commits
git cherry-pick abc123..def456

# Elegir commits específicos (no un rango)
git cherry-pick abc123 def456 ghi789

# Elegir los últimos 3 commits de otro branch
git cherry-pick feature~3..feature

Manejando conflictos en cherry-pick:

# Iniciar cherry-pick
git cherry-pick abc123

# Si hay un conflicto
# Arreglar los conflictos en tu editor
vim archivo-conflictivo.txt

# Agregar los archivos resueltos
git add archivo-conflictivo.txt

# Continuar el cherry-pick
git cherry-pick --continue

# O abortar si las cosas salen mal
git cherry-pick --abort

Opciones de cherry-pick:

# Cherry-pick pero no commitear (solo stagear cambios)
git cherry-pick -n abc123

# Cherry-pick y editar el mensaje del commit
git cherry-pick -e abc123

# Cherry-pick y agregar mensaje "cherry picked from"
git cherry-pick -x abc123

# Esto agrega una línea como:
# (cherry picked from commit abc123...)

Técnicas Avanzadas de Reflog

Buscando en el reflog:

# Encontrar todos los commits con mensaje específico
git reflog --grep="feature"

# Mostrar reflog para branch específico
git reflog show feature-branch

# Mostrar reflog con fechas
git reflog --date=relative

# Mostrar reflog para todas las referencias
git reflog show --all

Recuperación basada en tiempo:

# Ver dónde estaba HEAD ayer
git show HEAD@{yesterday}

# Ver dónde estaba HEAD hace 2 horas
git show HEAD@{2.hours.ago}

# Reset a donde estabas esta mañana
git reset --hard HEAD@{10.hours.ago}

# Ver cómo se veía main la semana pasada
git show main@{1.week.ago}

Limpiando después de recuperar:

# Después de recuperar commits, limpiar branches duplicados
git branch --merged | grep -v main | xargs git branch -d

# Recolección de basura para limpiar objetos sin referencia (¡cuidado!)
git gc --prune=now

# Ver qué se limpiaría
git fsck --unreachable

Escenarios de Recuperación del Mundo Real

Escenario 1: Trabajo perdido después de force push

# Alguien hizo force-push al remoto
git pull
# ¡Tu trabajo local parece haberse ido!

# Encontrar tu trabajo en reflog
git reflog
# Encontrar tu último commit antes del pull

# Crear un branch desde tu trabajo
git branch mi-trabajo-salvado HEAD@{1}

# Ahora merge o rebase tu trabajo de vuelta
git rebase origin/main mi-trabajo-salvado

Escenario 2: Recuperando una versión específica de archivo

# Necesitás un archivo de un commit borrado
git reflog
# Encontrar el commit: abc123

# Obtener el archivo sin hacer checkout del commit
git show abc123:ruta/al/archivo.js > archivo-recuperado.js

# O restaurarlo directamente
git checkout abc123 -- ruta/al/archivo.js

Escenario 3: Deshacer las últimas operaciones

# Hiciste varias operaciones y querés deshacerlas todas
git reflog
# Ver tu último punto "seguro"

# Crear un backup del estado actual
git branch backup-actual

# Reset al punto seguro
git reset --hard HEAD@{10}

Mejores Prácticas y Tips de Seguridad

1. Siempre crear branches de backup antes de operaciones peligrosas:

# Antes de rebase
git branch backup-antes-rebase

# Antes de reset
git branch backup-antes-reset

# Antes de merge
git branch backup-antes-merge

2. Usar git stash para seguridad temporal:

# Guardar trabajo actual antes de experimentar
git stash save "Antes de intentar operación peligrosa"

# Hacer tu operación peligrosa
git rebase -i HEAD~10

# Si las cosas salen mal, reset y restaurar stash
git reset --hard ORIG_HEAD
git stash pop

3. Configurar reflog para mantener entradas más tiempo:

# Mantener entradas de reflog por 180 días
git config gc.reflogExpire 180.days

# Mantener objetos inalcanzables por 60 días
git config gc.reflogExpireUnreachable 60.days

4. Aprender a leer patrones de reflog:

  • HEAD@{n}: La enésima posición anterior de HEAD
  • branch@{n}: La enésima posición anterior de un branch específico
  • @{-n}: El enésimo branch del que hiciste checkout antes del actual
  • @{upstream}: El branch upstream

Cherry-Pick vs Merge vs Rebase

¿Cuándo deberías usar cherry-pick en lugar de merge o rebase?


Usar cherry-pick cuando:

  • Necesitás commits específicos, no branches enteros
  • Backporting de fixes a branches de release
  • Mover un commit al branch correcto
  • Extraer commits de branches abandonados

Usar merge cuando:

  • Combinar branches de features enteros
  • Preservar historial completo
  • Trabajar con branches compartidos

Usar rebase cuando:

  • Limpiar historial local antes de pushear
  • Actualizar feature branch con main
  • Mantener historial lineal

Solucionando Problemas Comunes

“fatal: ambiguous argument ‘HEAD@{n}’”

# Escapar las llaves en algunos shells
git reset --hard 'HEAD@{1}'
# o
git reset --hard HEAD@\{1\}

“warning: reflog of ‘branch’ references pruned commits”

# Los commits siguen ahí, solo inalcanzables
# Encontrarlos con
git fsck --unreachable | grep commit

# Recuperar commit inalcanzable específico
git show <sha-inalcanzable>
git branch recuperado <sha-inalcanzable>

“error: could not apply abc123”

# Conflicto de cherry-pick
# Ver qué está en conflicto
git status

# Ver las diferencias
git diff

# Resolver y continuar, o abortar
git cherry-pick --abort

Conclusión

El reflog de Git es tu red de seguridad, y cjerry-pick es tu herramienta de precisión. Juntos, hacen que Git sea mucho menos aterrador. Recordá:


  • Git raramente borra algo verdaderamente de inmediato
  • El reflog es tu máquina del tiempo - ¡usala!
  • Cherry-pick cuando necesites precisión quirúrgica
  • Siempre creá branches de backup antes de operaciones riesgosas
  • Cuando tengas dudas, verificá el reflog

La próxima vez que pienses que perdiste trabajo en Git, no entres en pánico. Respirá, verificá el reflog, y recordá que tus commits probablemente están a solo unos comandos de distancia de ser recuperados. Git te cubre las espaldas, ¡solo necesitás saber cómo pedir ayuda!


Practicá estos comandos en un repositorio de prueba hasta que se vuelvan segunda naturaleza. La confianza de saber que podés recuperarte de casi cualquier error de Git es invaluable.


¡Hasta la próxima, que tus commits estén seguros y tu reflog siempre accesible!


$ Comentarios

Online: 0

Por favor inicie sesión para poder escribir comentarios.

2025-09-09 | Gabriel Garrido