FLUJOS DE TRABAJO AVANZADOS EN GIT Rebase Squash Reword rebase -i Bisect Busqueda Binaria Caza de Bugs bisect good/bad Hooks pre-commit commit-msg .git/hooks/ Reflog Recuperacion Deshacer Errores reflog expire Worktree Dev Paralelo Multi-rama worktree add git rebase | git bisect | git hooks | git reflog | git worktree Domina los comandos avanzados de Git para flujos de trabajo profesionales

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 --version para 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:

HookDisparadorUso Comun
pre-commitAntes de crear un commitLinting, formateo, pruebas
commit-msgDespues de ingresar el mensaje de commitValidar formato del mensaje
pre-pushAntes de hacer push a un remotoEjecutar suite completa de pruebas
post-mergeDespues de completar un mergeInstalar dependencias
pre-rebaseAntes de iniciar un rebasePrevenir 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

ComandoDescripcionEjemplo
git rebase -i HEAD~NRebase interactivo para los ultimos N commitsgit rebase -i HEAD~5
git bisect startIniciar busqueda binaria para bugsgit bisect start
git bisect run <script>Bisect automatizado con un script de pruebagit bisect run npm test
git cherry-pick <SHA>Aplicar un commit especifico a la rama actualgit cherry-pick a1b2c3d
git cherry-pick --no-commitCherry-pick sin auto-commitgit cherry-pick --no-commit a1b2c3d
git reflogMostrar historial de movimientos de HEADgit reflog
git worktree add <ruta> <rama>Hacer checkout de una rama en un directorio separadogit worktree add ../fix main
git stash push -m "msg"Guardar cambios con un mensaje descriptivogit stash push -m "WIP auth"
git stash push -pStash interactivo de hunks seleccionadosgit stash push -p
git blame -L 10,20 <archivo>Blame de un rango de lineas especificogit blame -L 10,20 auth.js
git log -S "cadena"Encontrar commits que agregan/eliminan una cadenagit log -S "loginUser"
git log -G "regex"Encontrar commits que coincidan con una regexgit log -G "TODO|FIXME"
git commit --fixup=<SHA>Crear un commit fixup para autosquashgit commit --fixup=a1b2c3d
git config core.hooksPathEstablecer un directorio de hooks personalizadogit 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.