La mayoria de los desarrolladores aprenden git add, git commit y git push — y luego se detienen ahi. Pero Git es una herramienta extraordinariamente poderosa con comandos que pueden ahorrarte horas de trabajo, ayudarte a rastrear bugs en segundos, automatizar la aplicacion de calidad de codigo y recuperarte de errores que de otro modo serian catastroficos. Esta guia cubre los flujos de trabajo avanzados de Git que separan a los usuarios cotidianos de los usuarios expertos: rebase interactivo, bisect, hooks, recuperacion con reflog, cherry-pick, worktrees y mas.
Para quien es esto: Este articulo asume que te sientes comodo con las operaciones basicas de Git (commit, push, pull, branch, merge). Si aun estas aprendiendo esos fundamentos, comienza ahi primero y regresa cuando estes listo para subir de nivel.
Requisitos Previos
Antes de sumergirte en los flujos de trabajo avanzados, asegurate de tener:
- Git 2.23 o posterior instalado (ejecuta
git --versionpara verificar) - Un repositorio con al menos 20-30 commits para practicar
- Familiaridad con ramificacion y fusion basica
- Una terminal con la que te sientas comodo (Bash, Zsh, PowerShell)
# Verificar tu version de Git
git --version
# Actualizar Git en Ubuntu/Debian
sudo apt update && sudo apt install git
# Actualizar Git en macOS
brew upgrade git
Consejo: Crea un repositorio desechable para practicar estos comandos. Muchos de ellos reescriben el historial, y quieres ganar confianza antes de usarlos en codigo de produccion.
Rebase Interactivo
El rebase interactivo es posiblemente la herramienta de edicion de commits mas poderosa en Git. Te permite reescribir, combinar, reordenar y eliminar commits antes de hacer push a una rama compartida.
Iniciar un Rebase Interactivo
Para modificar los ultimos 5 commits:
git rebase -i HEAD~5
Esto abre tu editor con una lista de commits, del mas antiguo al mas reciente:
pick a1b2c3d Add user authentication
pick e4f5g6h Fix typo in login form
pick i7j8k9l Add password reset feature
pick m0n1o2p Fix lint errors
pick q3r4s5t Update README
Comandos de Rebase
Cada linea de commit comienza con un comando. Los mas utiles son:
- pick — Mantener el commit tal como esta
- reword — Mantener el commit pero cambiar el mensaje
- squash — Combinar este commit con el anterior (mantiene ambos mensajes)
- fixup — Combinar con el commit anterior (descarta el mensaje de este commit)
- edit — Pausar el rebase en este commit para poder enmendarlo
- drop — Eliminar este commit completamente
Combinar Commits (Squash)
El uso mas comun del rebase interactivo es combinar multiples commits pequenos en uno significativo:
pick a1b2c3d Add user authentication
fixup e4f5g6h Fix typo in login form
pick i7j8k9l Add password reset feature
fixup m0n1o2p Fix lint errors
drop q3r4s5t Update README
Esto produce dos commits limpios en lugar de cinco desordenados.
Reordenar Commits
Simplemente reorganiza las lineas en tu editor para cambiar el orden de los commits:
pick i7j8k9l Add password reset feature
pick a1b2c3d Add user authentication
Advertencia: Nunca hagas rebase de commits que ya se hayan enviado a una rama compartida. Reescribir historial compartido causa conflictos para todos en tu equipo. Solo haz rebase de tus commits locales no enviados.
Autosquash con Commits de Correccion
Si sabes que un commit es una correccion para uno anterior, marcalo al momento del commit:
# Crear un commit fixup que se auto-combina con el commit objetivo
git commit --fixup=a1b2c3d
# Despues, autosquash durante el rebase
git rebase -i --autosquash HEAD~10
Git automaticamente reordena los commits fixup junto a sus objetivos y los marca con fixup.
Git Bisect: Busqueda Binaria para Bugs
Cuando aparece un bug y no sabes cual commit lo introdujo, probar cada commit uno por uno es impractico. git bisect realiza una busqueda binaria, encontrando el commit exacto en O(log n) pasos.
Bisect Manual
# Iniciar la biseccion
git bisect start
# Marcar el commit actual como malo (tiene el bug)
git bisect bad
# Marcar un commit bueno conocido (antes de que existiera el bug)
git bisect good v2.0.0
# Git hace checkout del punto medio -- pruebalo
# Si este commit tiene el bug:
git bisect bad
# Si este commit no tiene el bug:
git bisect good
# Repetir hasta que Git identifique el primer commit malo
# Cuando termines:
git bisect reset
Para un rango de 1,024 commits, bisect encuentra al culpable en aproximadamente 10 pasos.
Bisect Automatizado con un Script
Si tienes un script de prueba que retorna codigo de salida 0 para bueno y distinto de cero para malo:
git bisect start
git bisect bad HEAD
git bisect good v2.0.0
# Ejecutar la prueba automaticamente en cada paso
git bisect run ./test-script.sh
# O usar un comando de prueba especifico
git bisect run npm test -- --grep "login feature"
Git ejecuta el script en cada punto medio e identifica el commit culpable sin ninguna intervencion manual.
Bisect con Criterios Complejos
# Saltar commits que no se pueden probar (ej., build roto)
git bisect skip
# Ver el log de bisect
git bisect log
# Reproducir una sesion de bisect desde un archivo de log
git bisect replay bisect-log.txt
Estrategias de Cherry-Pick
Cherry-pick aplica un commit especifico de una rama a otra sin fusionar la rama completa. Es util para hotfixes, backporting e integracion selectiva de funcionalidades.
Cherry-Pick Basico
# Aplicar un solo commit a tu rama actual
git cherry-pick abc1234
# Aplicar multiples commits
git cherry-pick abc1234 def5678 ghi9012
# Aplicar un rango de commits (excluyendo el primero)
git cherry-pick abc1234..ghi9012
Cherry-Pick Sin Hacer Commit
# Preparar los cambios pero no hacer commit (util para combinar multiples picks)
git cherry-pick --no-commit abc1234
git cherry-pick --no-commit def5678
# Revisar los cambios combinados, luego hacer commit
git commit -m "Backport: authentication fixes from develop"
Manejar Conflictos de Cherry-Pick
# Si ocurre un conflicto durante el cherry-pick:
# 1. Resolver los conflictos en los archivos afectados
# 2. Agregar los archivos resueltos al staging
git add resolved-file.js
# 3. Continuar el cherry-pick
git cherry-pick --continue
# O abortar todo el cherry-pick
git cherry-pick --abort
Cherry-Pick para Hotfixes
Un patron comun para hotfixes en produccion:
# En la rama main, corregir el bug
git checkout main
git checkout -b hotfix/login-crash
# Hacer la correccion y commit
git commit -am "Fix: prevent null pointer in login handler"
# Fusionar a main
git checkout main
git merge hotfix/login-crash
# Cherry-pick la correccion a la rama develop
git checkout develop
git cherry-pick <hotfix-commit-sha>
Git Hooks
Los Git hooks son scripts que se ejecutan automaticamente en puntos especificos del ciclo de vida de Git. Aplican calidad de codigo, validan mensajes de commit y previenen que codigo defectuoso entre al repositorio.
Tipos de Hooks y Ubicaciones
Los hooks se encuentran en .git/hooks/. Los hooks mas utilizados son:
| Hook | Disparador | Uso Comun |
|---|---|---|
pre-commit | Antes de crear un commit | Linting, formateo, pruebas |
commit-msg | Despues de ingresar el mensaje de commit | Validar formato del mensaje |
pre-push | Antes de hacer push a un remoto | Ejecutar suite completa de pruebas |
post-merge | Despues de completar un merge | Instalar dependencias |
pre-rebase | Antes de iniciar un rebase | Prevenir rebase en ramas compartidas |
Hook Pre-Commit: Linting
#!/bin/sh
# .git/hooks/pre-commit
# Ejecutar ESLint en archivos JavaScript preparados
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')
if [ -n "$STAGED_FILES" ]; then
echo "Running ESLint on staged files..."
npx eslint $STAGED_FILES
if [ $? -ne 0 ]; then
echo "ESLint failed. Fix errors before committing."
exit 1
fi
fi
# Ejecutar verificacion de Prettier
STAGED_ALL=$(git diff --cached --name-only --diff-filter=ACM)
if [ -n "$STAGED_ALL" ]; then
npx prettier --check $STAGED_ALL
if [ $? -ne 0 ]; then
echo "Prettier check failed. Run 'npx prettier --write .' first."
exit 1
fi
fi
exit 0
Hook Commit-Msg: Conventional Commits
#!/bin/sh
# .git/hooks/commit-msg
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# Aplicar formato Conventional Commits
PATTERN="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,72}"
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
echo "ERROR: Commit message does not follow Conventional Commits format."
echo ""
echo "Expected: <type>(<scope>): <description>"
echo "Example: feat(auth): add password reset endpoint"
echo ""
echo "Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
exit 1
fi
exit 0
Hook Pre-Push: Suite de Pruebas
#!/bin/sh
# .git/hooks/pre-push
echo "Running test suite before push..."
npm test
if [ $? -ne 0 ]; then
echo "Tests failed. Push aborted."
echo "Fix failing tests before pushing."
exit 1
fi
echo "All tests passed. Pushing..."
exit 0
Compartir Hooks con Tu Equipo
Los hooks en .git/hooks/ no son rastreados por Git. Para compartirlos:
# Opcion 1: Almacenar hooks en un directorio rastreado
mkdir -p .githooks
cp .git/hooks/pre-commit .githooks/
# Configurar Git para usar el directorio rastreado
git config core.hooksPath .githooks
# Opcion 2: Usar Husky (proyectos Node.js)
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"
Git Reflog y Recuperacion
El reflog es tu red de seguridad. Registra cada cambio a HEAD — commits, rebases, resets, checkouts — durante al menos 30 dias. Si pierdes commits, el reflog es como los recuperas.
Ver el Reflog
# Ver el reflog
git reflog
# La salida se ve asi:
# a1b2c3d HEAD@{0}: commit: Add new feature
# e4f5g6h HEAD@{1}: rebase -i (finish): returning to refs/heads/main
# i7j8k9l HEAD@{2}: rebase -i (squash): Add user auth
# m0n1o2p HEAD@{3}: reset: moving to HEAD~3
Recuperar Despues de un Reset Incorrecto
# Accidentalmente ejecutaste git reset --hard HEAD~3 y perdiste 3 commits
# Paso 1: Encontrar el commit perdido en el reflog
git reflog
# Paso 2: El commit antes del reset esta en HEAD@{1}
git checkout HEAD@{1}
# Paso 3: Crear una rama para guardarlo
git checkout -b trabajo-recuperado
# O hacer cherry-pick de commits especificos de vuelta
git cherry-pick a1b2c3d
Recuperar Despues de un Rebase Incorrecto
# Si un rebase salio mal, encontrar el estado antes del rebase
git reflog
# Buscar la entrada justo antes de "rebase -i (start)"
# Resetear a ese punto
git reset --hard HEAD@{5}
Recuperar Ramas Eliminadas
# Eliminaste una rama con trabajo importante
git branch -D feature/trabajo-importante
# Encontrar la punta de la rama en el reflog
git reflog | grep "trabajo-importante"
# Recrear la rama en el SHA encontrado
git branch feature/trabajo-importante abc1234
Importante: Las entradas del reflog expiran despues de 90 dias (30 dias para commits inalcanzables). Si descubres trabajo perdido, recuperalo lo antes posible. Puedes configurar la expiracion con
git config gc.reflogExpire.
Git Worktree: Desarrollo en Paralelo
Los worktrees te permiten tener multiples ramas abiertas simultaneamente en directorios separados. No mas stashing, committing o cambio de ramas para revisar un pull request o corregir un hotfix.
Crear un Worktree
# Hacer checkout de una rama en un nuevo directorio
git worktree add ../hotfix-branch hotfix/login-fix
# Crear una nueva rama en un worktree
git worktree add -b feature/new-api ../new-api-work
# Listar todos los worktrees
git worktree list
Flujo de Trabajo Practico con Worktrees
# Tu directorio principal de trabajo tiene develop en checkout
# Llega un bug de produccion -- trabajalo sin interrumpir tu trabajo actual
git worktree add ../prod-fix main
cd ../prod-fix
# Corregir el bug en una nueva rama
git checkout -b hotfix/critical-fix
# ... hacer cambios, commit, push ...
# Regresar a tu trabajo de funcionalidad
cd ../my-project
# develop esta exactamente donde lo dejaste
# Limpiar cuando termines
git worktree remove ../prod-fix
Worktree para Revision de Codigo
# Revisar el PR de un colega sin dejar tu rama actual
git fetch origin
git worktree add ../review-pr-42 origin/feature/user-dashboard
# Abrir el worktree en tu editor, revisar el codigo
# Cuando termines:
git worktree remove ../review-pr-42
Uso Avanzado del Stash
Mas alla del basico git stash, hay opciones poderosas para gestionar cambios en progreso.
Stashes con Nombre
# Stash con un mensaje descriptivo
git stash push -m "WIP: refactoring auth middleware"
# Listar todos los stashes
git stash list
# stash@{0}: On develop: WIP: refactoring auth middleware
# stash@{1}: On develop: WIP: database migration script
Stash Parcial
# Hacer stash solo de archivos especificos
git stash push -m "stash auth changes" src/auth.js src/middleware.js
# Stash interactivo -- elegir hunks individuales
git stash push -p -m "partial stash"
Stash Apply vs. Pop
# Apply mantiene el stash en la lista (seguro para intentar de nuevo)
git stash apply stash@{0}
# Pop aplica y elimina el stash de la lista
git stash pop stash@{0}
# Aplicar stash a una rama diferente
git checkout feature/otra-rama
git stash apply stash@{0}
Crear una Rama desde un Stash
# Crear una nueva rama y aplicar el stash en ella
git stash branch nueva-rama-feature stash@{0}
Esto es particularmente util cuando el stash tiene conflictos con los cambios en la rama actual.
Git Blame y Forensia de Log
Cuando necesitas entender por que existe una linea de codigo o rastrear cuando se introdujo un cambio, las herramientas de forensia de Git son indispensables.
Git Blame
# Ver quien modifico cada linea por ultima vez
git blame src/auth.js
# Blame de un rango de lineas especifico
git blame -L 10,20 src/auth.js
# Ignorar cambios de espacios en blanco
git blame -w src/auth.js
# Mostrar el commit que movio o copio la linea desde otro archivo
git blame -C src/auth.js
Busquedas Avanzadas de Log
# Buscar en mensajes de commit por una palabra clave
git log --grep="authentication" --oneline
# Buscar cambios en una funcion especifica
git log -p -S "function loginUser" -- src/
# Buscar cambios que coincidan con una regex
git log -p -G "TODO|FIXME|HACK"
# Ver historial de un archivo especifico
git log --follow --oneline -- src/auth.js
# Mostrar commits de un autor especifico en un rango de fechas
git log --author="JC" --after="2025-01-01" --before="2025-12-31" --oneline
Formatos Visuales de Log
# Grafico compacto de ramas
git log --oneline --graph --all --decorate
# Formato personalizado con fecha y autor
git log --pretty=format:"%h %ad | %s%d [%an]" --date=short
# Mostrar estadisticas por commit
git log --stat --oneline -10
Estrategias de Ramificacion
Elegir la estrategia de ramificacion correcta afecta la velocidad y calidad de codigo de tu equipo.
Git Flow
Git Flow usa ramas de larga duracion para diferentes etapas:
# Ramas principales
main # Codigo listo para produccion
develop # Rama de integracion para funcionalidades
# Ramas de soporte
feature/* # Nuevas funcionalidades (ramificar desde develop)
release/* # Preparacion de lanzamiento (ramificar desde develop)
hotfix/* # Correcciones de produccion (ramificar desde main)
# Iniciar una funcionalidad
git checkout develop
git checkout -b feature/user-dashboard
# Finalizar una funcionalidad
git checkout develop
git merge --no-ff feature/user-dashboard
git branch -d feature/user-dashboard
Ideal para: Equipos con lanzamientos programados y multiples entornos.
GitHub Flow
Una alternativa mas simple con una regla: todo lo que esta en main es desplegable.
# Crear una rama desde main
git checkout main
git checkout -b feature/add-search
# Trabajar, hacer commit, push
git push -u origin feature/add-search
# Abrir un Pull Request, obtener revision, fusionar a main
# El despliegue ocurre automaticamente desde main
Ideal para: Equipos que practican despliegue continuo con ramas de corta duracion.
Desarrollo Basado en Trunk
Todos los desarrolladores hacen commit a main (el trunk) frecuentemente, usando ramas de funcionalidad de corta duracion de uno a dos dias maximo.
# Rama de corta duracion (1-2 dias maximo)
git checkout -b feature/small-change
# ... cambios minimos ...
git push -u origin feature/small-change
# Fusionar a main rapidamente via PR
# Los feature flags controlan funcionalidades no lanzadas
if (featureFlags.newDashboard) {
renderNewDashboard();
}
Ideal para: Equipos de alta velocidad con pipelines CI/CD solidos e infraestructura de feature flags.
Tabla de Referencia de Comandos Avanzados de Git
| Comando | Descripcion | Ejemplo |
|---|---|---|
git rebase -i HEAD~N | Rebase interactivo para los ultimos N commits | git rebase -i HEAD~5 |
git bisect start | Iniciar busqueda binaria para bugs | git bisect start |
git bisect run <script> | Bisect automatizado con un script de prueba | git bisect run npm test |
git cherry-pick <SHA> | Aplicar un commit especifico a la rama actual | git cherry-pick a1b2c3d |
git cherry-pick --no-commit | Cherry-pick sin auto-commit | git cherry-pick --no-commit a1b2c3d |
git reflog | Mostrar historial de movimientos de HEAD | git reflog |
git worktree add <ruta> <rama> | Hacer checkout de una rama en un directorio separado | git worktree add ../fix main |
git stash push -m "msg" | Guardar cambios con un mensaje descriptivo | git stash push -m "WIP auth" |
git stash push -p | Stash interactivo de hunks seleccionados | git stash push -p |
git blame -L 10,20 <archivo> | Blame de un rango de lineas especifico | git blame -L 10,20 auth.js |
git log -S "cadena" | Encontrar commits que agregan/eliminan una cadena | git log -S "loginUser" |
git log -G "regex" | Encontrar commits que coincidan con una regex | git log -G "TODO|FIXME" |
git commit --fixup=<SHA> | Crear un commit fixup para autosquash | git commit --fixup=a1b2c3d |
git config core.hooksPath | Establecer un directorio de hooks personalizado | git config core.hooksPath .githooks |
Solucion de Problemas
Los Conflictos de Rebase No Se Resuelven
# Si un rebase tiene demasiados conflictos, abortar e intentar otro enfoque
git rebase --abort
# Alternativa: usar merge en lugar de rebase para historiales complejos
git merge develop
Bisect Da Resultados Incorrectos
# Si marcaste un commit incorrectamente, ver el log y reproducir
git bisect log > bisect-log.txt
# Editar el archivo de log para eliminar la entrada incorrecta
git bisect reset
git bisect replay bisect-log.txt
Los Scripts de Hook No Se Ejecutan
# Asegurar que el archivo de hook sea ejecutable
chmod +x .git/hooks/pre-commit
# Verificar que la linea shebang sea correcta
head -1 .git/hooks/pre-commit
# Deberia ser: #!/bin/sh o #!/bin/bash
# Verificar si core.hooksPath sobreescribe la ubicacion por defecto
git config --get core.hooksPath
No Se Puede Eliminar un Worktree
# Forzar la eliminacion de un worktree con cambios sin commit
git worktree remove --force ../old-worktree
# Limpiar entradas de worktree obsoletas
git worktree prune
Entrada de Reflog No Encontrada
# Aumentar el tiempo de expiracion del reflog antes de que sea demasiado tarde
git config gc.reflogExpire 180.days
git config gc.reflogExpireUnreachable 90.days
# Si el reflog esta vacio, intentar fsck para encontrar commits colgantes
git fsck --unreachable --no-reflogs
Cherry-Pick Resulta en un Commit Vacio
# Los cambios ya existen en la rama destino
# Usar --allow-empty para mantener el commit, o saltarlo
git cherry-pick --skip
# O verificar si el cambio ya fue aplicado
git log --oneline --all -- path/to/changed/file
Resumen
Los flujos de trabajo avanzados de Git transforman la forma en que gestionas el codigo. El rebase interactivo mantiene tu historial de commits limpio y significativo. Git bisect convierte una busqueda manual de bugs en una busqueda binaria automatizada. Los Git hooks aplican estandares de calidad de codigo antes de que codigo defectuoso entre al repositorio. Reflog actua como tu red de seguridad, haciendo que virtualmente cada error de Git sea recuperable. Cherry-pick y worktrees proporcionan la flexibilidad para trabajar entre ramas sin interrupciones.
La clave es la practica. Crea un repositorio de prueba, haz docenas de commits y prueba cada comando de esta guia. Una vez que estas herramientas se conviertan en algo natural, manejaras situaciones complejas de Git con confianza.
Para automatizar tus pipelines de pruebas y despliegue despues de dominar estos flujos de trabajo de Git, lee nuestra guia sobre Primeros Pasos con GitHub Actions para CI/CD.