Utilidades de Git
Herramientas avanzadas para situaciones cotidianas — guardar WIP, encontrar commits que introducen bugs, mover commits entre ramas y recuperarse de errores.
Receta
Tarjeta de referencia rápida — lista para copiar y pegar.
# Guarda los cambios actuales
git stash
git stash pop
# Realiza cherry-pick de un commit de otra rama
git cherry-pick abc1234
# Encuentra el commit que introdujo un bug
git bisect start
git bisect bad # el commit actual está roto
git bisect good v1.0.0 # esta etiqueta funcionaba
# Git copia commits para que los pruebes, luego:
git bisect good # o git bisect bad
git bisect reset # cuando termines
# Recupera un commit perdido
git reflog
git checkout -b recovery abc1234Cuándo usarlo: Cuando los comandos básicos add/commit/branch no son suficientes — cambio de contexto, depuración de regresiones, mover commits específicos o recuperarse de errores.
Ejemplo Práctico
Stash — Cambio de Contexto Rápido
# Estás a mitad de una feature pero necesitas arreglar un bug en main
git stash -m "WIP: componente de gráfico de panel de control"
git checkout main
git checkout -b hotfix/login-error
# ... arregla el bug, haz commit, envía, fusiona ...
git checkout feature/dashboard
git stash pop
# De vuelta a tu WIP exactamente donde lo dejasteQué demuestra esto:
- Los stashes nombrados con
-mfacilitan identificarlos después stash popaplica y elimina el stash en un paso- Tu directorio de trabajo se restaura exactamente como estaba
Cherry-Pick — Obtén un Commit Específico
# Un compañero de equipo arregló una función auxiliar en su rama
# Necesitas solo ese commit, no toda su rama
git cherry-pick abc1234
# Realiza cherry-pick sin hacer commit (solo prepara cambios)
git cherry-pick --no-commit abc1234
# Realiza cherry-pick de un rango de commits
git cherry-pick abc1234..def5678Qué demuestra esto:
- Cherry-pick copia un commit, creando un nuevo commit con un nuevo hash
--no-committe permite modificar los cambios antes de hacer commit- Útil para retroactivamente transferir correcciones a ramas de lanzamiento
Profundización
Gestión de Stash
# Guarda incluyendo archivos no rastreados
git stash -u
# Guarda incluyendo archivos ignorados
git stash -a
# Lista todos los stashes
git stash list
# stash@{0}: On feature/dashboard: WIP: componente de gráfico
# stash@{1}: On main: experimento rápido
# Aplica un stash específico (mantenlo en la lista)
git stash apply stash@{1}
# Elimina un stash específico
git stash drop stash@{1}
# Limpia todos los stashes
git stash clear
# Crea una rama a partir de un stash
git stash branch new-feature stash@{0}
# Muestra lo que contiene un stash
git stash show -p stash@{0}Bisect — Búsqueda Binaria de Bugs
git bisect realiza una búsqueda binaria a través de tu historial de commits para encontrar exactamente qué commit introdujo el bug.
# Bisect manual
git bisect start
git bisect bad # HEAD está roto
git bisect good abc1234 # este commit funcionaba
# Git copia un commit a mitad de camino entre good y bad
# Pruébalo, luego dile a Git:
git bisect good # este commit funciona bien
# o
git bisect bad # este commit está roto
# Repite hasta que Git encuentre el primer commit roto
# "abc1234 es el primer commit roto"
git bisect reset # vuelve a tu rama original
# Bisect automatizado con un script de prueba
git bisect start HEAD abc1234
git bisect run npm test
# Git ejecuta automáticamente la prueba en cada paso
# Código de salida 0 = good, no cero = badReflog — Tu Red de Seguridad
Reflog registra cada vez que HEAD se mueve. Es tu historial de deshacer para Git mismo.
# Ver reflog
git reflog
# abc1234 HEAD@{0}: commit: feat: agregar búsqueda
# def5678 HEAD@{1}: rebase (finish): devolviendo a refs/heads/feature
# ghi9012 HEAD@{2}: rebase (start): copiando main
# jkl3456 HEAD@{3}: commit: feat: agregar panel de control
# Recuperarse después de un rebase incorrecto
git reflog
# Encuentra el hash del commit antes de que comenzara el rebase
git reset --hard HEAD@{3}
# Recupera una rama eliminada
git reflog
# Encuentra el último commit en la rama eliminada
git checkout -b recovered-branch abc1234Clean — Elimina Archivos No Rastreados
# Previsualiza lo que se eliminaría (ejecución en seco)
git clean -n
# Elimina archivos no rastreados
git clean -f
# Elimina archivos y directorios no rastreados
git clean -fd
# Elimina archivos ignorados también (reinicio completo)
git clean -fdx
# Modo interactivo
git clean -iEtiquetas
# Crea una etiqueta ligera
git tag v1.0.0
# Crea una etiqueta anotada (recomendada para lanzamientos)
git tag -a v1.0.0 -m "Release version 1.0.0"
# Etiqueta un commit específico
git tag -a v0.9.0 abc1234 -m "Beta release"
# Lista etiquetas
git tag -l
git tag -l "v1.*"
# Envía etiquetas al repositorio remoto
git push origin v1.0.0
git push origin --tags
# Elimina una etiqueta
git tag -d v1.0.0
git push origin --delete v1.0.0Reset vs Revert
# Reset — mueve HEAD hacia atrás (reescribe el historial)
git reset --soft HEAD~1 # deshacer commit, mantener cambios preparados
git reset --mixed HEAD~1 # deshacer commit, mantener cambios sin preparar (por defecto)
git reset --hard HEAD~1 # deshacer commit, descartar cambios completamente
# Revert — crea un nuevo commit que deshace uno anterior (seguro para ramas compartidas)
git revert abc1234
git revert HEAD~3..HEAD # revertir un rango
git revert --no-commit abc1234 # prepara la reversión sin hacer commitRegla general: Usa reset en commits locales/no enviados. Usa revert en commits compartidos/enviados.
Worktrees — Múltiples Ramas Simultáneamente
# Crea un worktree para una rama diferente
git worktree add ../project-hotfix hotfix/login-error
# Lista worktrees
git worktree list
# Elimina un worktree cuando hayas terminado
git worktree remove ../project-hotfixLos worktrees te permiten tener múltiples ramas copiadas simultáneamente en directorios separados — sin necesidad de stash.
Trampas
Cosas que te van a picar. Cada trampa incluye qué sale mal, por qué ocurre y la solución.
-
Stash pop con conflictos —
git stash popintenta aplicar y eliminar el stash. Si hay conflictos, el stash NO se elimina. Solución: Resuelve conflictos, luego ejecutagit stash dropmanualmente. -
Cherry-pick crea commits duplicados — El commit copiado obtiene un nuevo hash. Si la rama de origen se fusiona después, tendrás dos copias. Solución: Esto generalmente es inofensivo — Git lo maneja durante la fusión. Pero por claridad, considera hacer rebase en su lugar.
-
Reset --hard pierde trabajo sin commit — No hay forma de recuperar cambios sin preparar después de
git reset --hard. Solución: Siempre ejecutagit stashantes de hacer un reset duro. O usagit reset --softpara mantener los cambios. -
Bisect olvidando hacer reset — Terminas bisecting pero olvidas
git bisect resety te quedas en un HEAD desasociado. Solución: Ejecutagit bisect resetpara volver a tu rama. -
Clean eliminando archivos necesarios —
git clean -fdxelimina todo lo que no está rastreado, incluyendo archivos.env. Solución: Siempre haz una ejecución en seco primero congit clean -n.
Alternativas
Otras formas de resolver el mismo problema — y cuándo cada una es la mejor opción.
| Alternativa | Úsalo Cuando | No lo Uses Cuando |
|---|---|---|
git stash vs hacer commit de WIP | Cambio de contexto rápido, volviendo pronto | Dejar WIP durante días — haz commit en una rama |
git revert vs git reset | El commit ya fue enviado/compartido | Commits solo locales donde reset es más limpio |
git cherry-pick vs git rebase | Necesitas uno o dos commits específicos | Necesitas los cambios de toda una rama |
git worktree vs git stash | Trabajo paralelo de larga duración en dos ramas | Cambio rápido de rama única |
Preguntas Frecuentes
¿Cuál es la diferencia entre git stash pop y git stash apply?
popaplica el stash y lo elimina de la listaapplyaplica el stash pero lo mantiene en la lista- Usa
applycuando quieras aplicar el mismo stash a múltiples ramas
¿Cómo hago stash solo de archivos específicos en lugar de todo?
git stash push -m "partial stash" src/components/Button.tsx- Puedes listar múltiples rutas de archivo después del mensaje
¿Qué hace git cherry-pick --no-commit?
- Aplica los cambios del commit copiado pero no crea un nuevo commit
- Los cambios se dejan preparados para que puedas modificarlos antes de hacer commit
- Útil cuando necesitas ajustar el código copiado por cherry-pick para un contexto diferente
¿Cómo funciona git bisect y cuándo deberías usarlo?
- Realiza una búsqueda binaria a través del historial de commits para encontrar el commit que introdujo el bug
- Marcas los commits como
goodobady Git lo reduce en pasos O(log n) - Úsalo cuando aparezca una regresión y no sepas qué commit la causó
¿Puedo automatizar git bisect con un script de prueba?
git bisect start HEAD v1.0.0
git bisect run npm test- Git ejecuta el script en cada paso; código de salida 0 = good, no cero = bad
- Búsqueda de bugs totalmente automática
Trampa: ¿Por qué git stash pop dejó mi stash en la lista después de un conflicto?
- Cuando
popencuentra un conflicto de fusión, aplica el stash pero no lo elimina - Resuelve los conflictos, luego ejecuta manualmente
git stash drop
¿Qué es reflog y cuánto tiempo conserva datos?
- Reflog registra cada movimiento de HEAD (commits, rebases, resets, checkouts)
- Las entradas expiran después de ~90 días por defecto
- Es solo local y no se comparte con repositorios remotos
¿Cómo recupero una rama que eliminé accidentalmente?
git reflog
# Encuentra el hash del commit en la rama eliminada
git checkout -b recovered-branch abc1234¿Cuál es la diferencia entre git reset y git revert?
resetmueve HEAD hacia atrás, reescribiendo el historial (úsalo en commits locales/no enviados)revertcrea un nuevo commit que deshace uno anterior (seguro para ramas compartidas)
Trampa: ¿Por qué git clean -fdx eliminó mi archivo .env?
- La bandera
-xelimina archivos ignorados por.gitignore, incluyendo.env - Siempre ejecuta
git clean -n(ejecución en seco) primero para ver una vista previa de lo que se eliminará
¿Cómo uso git worktree para trabajar en dos ramas a la vez?
git worktree add ../project-hotfix hotfix/login-error
# Trabaja en ../project-hotfix de forma independiente
git worktree remove ../project-hotfix- Cada worktree es un directorio separado con su propia rama copiada
Cuando trabajo en un proyecto de TypeScript, ¿cómo puedo etiquetar un lanzamiento?
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0- Usa etiquetas anotadas (
-a) para lanzamientos ya que almacenan autor, fecha y mensaje - Empareja con
npm versionpara actualizar automáticamente la versión depackage.json
Relacionado
- Comandos Git Esenciales — Preparación, commit, conceptos básicos de ramas
- Fusión & Rebase — Estrategias de integración de ramas
- GitHub CLI — Gestiona PRs, issues y lanzamientos desde la terminal