Saltar al contenido

Como desarrollador web con experiencia en proyectos complejos, probablemente ya dominas los comandos básicos de Git. Sin embargo, Git ofrece un conjunto de herramientas y técnicas avanzadas que pueden transformar la forma en que gestionas tu código y resuelves problemas. En esta entrada, exploraremos comandos avanzados de Git que he encontrado invaluables en mi trabajo diario con Laravel, Vue y otros frameworks modernos.

1. Git Reflog: Tu Red de Seguridad

Mientras que git log te muestra la historia de tus commits, git reflog registra todos los cambios en el estado de HEAD, incluyendo resets, merges, rebases fallidos y más:

git reflog

Este comando es invaluable cuando cometes un error como un hard reset accidental o un rebase problemático y necesitas recuperar trabajo aparentemente perdido.

Caso práctico: Imagina que has hecho un git reset --hard accidental y has perdido commits importantes:

# Ver el historial de todas las acciones
git reflog

# Recuperar el estado previo al reset
git reset --hard HEAD@{2}

2. Interactive Rebase: Reescribiendo la Historia con Elegancia

El rebase interactivo es una herramienta poderosa para limpiar y organizar tus commits antes de integrarlos en la rama principal:

git rebase -i HEAD~5

Este comando te permite:

  • Reorganizar el orden de los commits

  • Combinar múltiples commits en uno solo (squash)

  • Editar mensajes de commit

  • Eliminar commits no deseados

  • Dividir commits grandes en unidades lógicas más pequeñas

Caso práctico: Supongamos que has hecho varios commits pequeños durante el desarrollo de una función en tu aplicación Laravel y quieres presentar un historial de commits limpio y lógico antes de hacer merge a main:

# Iniciar rebase interactivo de los últimos 5 commits
git rebase -i HEAD~5

# En el editor, cambia 'pick' por 'squash' o 's' para los commits que quieres combinar
# También puedes usar 'reword' o 'r' para editar mensajes de commit

3. Git Bisect: Detección Eficiente de Bugs

El comando git bisect es una herramienta de diagnóstico que utiliza búsqueda binaria para ayudarte a encontrar el commit exacto que introdujo un bug:

# Iniciar la sesión de bisect
git bisect start

# Marcar el estado actual como malo
git bisect bad

# Marcar un commit anterior conocido como bueno
git bisect good [commit-hash]

# Git elegirá automáticamente un commit intermedio para probar
# Después de probar, marcar como 'good' o 'bad' y continuar
git bisect good  # o git bisect bad

# Cuando termines, finalizar la sesión
git bisect reset

Caso práctico: Has detectado un bug en tu aplicación Vue que no estaba presente hace una semana, pero no sabes exactamente qué cambio lo causó:

git bisect start
git bisect bad  # El estado actual tiene el bug
git bisect good HEAD@{1 week ago}  # Este punto estaba bien

# Git seleccionará automáticamente commits intermedios para probar
# Para cada uno, prueba tu aplicación y marca como good o bad

4. Git Worktree: Trabajar en Múltiples Ramas Simultáneamente

git worktree te permite tener múltiples copias de trabajo de tu repositorio, cada una en una rama diferente, sin necesidad de clonar todo el repositorio:

# Crear un nuevo worktree para una rama feature
git worktree add ../proyecto-feature feature

# Listar todos los worktrees
git worktree list

# Eliminar un worktree cuando ya no lo necesites
git worktree remove ../proyecto-feature

Caso práctico: Estás trabajando en una nueva funcionalidad en tu aplicación Laravel, pero surge un bug crítico que necesita ser solucionado inmediatamente:

# Crear un worktree para solucionar el bug sin interrumpir tu trabajo actual
git worktree add ../hotfix hotfix-branch

# Trabaja en la solución del bug en ../hotfix
# Mientras tanto, puedes seguir trabajando en tu funcionalidad en el directorio original

5. Cherry-Pick: Seleccionar Commits Específicos

git cherry-pick te permite aplicar cambios introducidos por commits específicos a tu rama actual:

git cherry-pick [commit-hash]

Caso práctico: Has implementado una función en una rama experimental que quieres incorporar a tu rama principal, pero no quieres hacer merge de toda la rama:

# Identificar el hash del commit que contiene la función deseada
git log --oneline feature-branch

# Aplicar solo ese commit a tu rama actual
git cherry-pick abc1234

6. Stash Avanzado: Gestión Sofisticada de Cambios en Progreso

Git stash es más potente de lo que muchos desarrolladores aprovechan:

# Guardar cambios no commiteados incluyendo archivos no rastreados
git stash --include-untracked

# Guardar con un mensaje descriptivo
git stash save "Implementación parcial de autenticación con Sanctum"

# Visualizar el contenido de un stash específico
git stash show -p stash@{1}

# Aplicar un stash específico sin eliminarlo
git stash apply stash@{2}

# Crear una rama a partir de un stash
git stash branch nueva-rama stash@{0}

Caso práctico: Estás en medio de implementar una función compleja en tu aplicación Vue cuando surge la necesidad de cambiar rápidamente a otra tarea:

# Guardar tu trabajo con un mensaje descriptivo
git stash save "Componente de dashboard a medio terminar"

# Cambiar a otra rama para la tarea urgente
git checkout otra-rama

# Cuando regreses a tu trabajo original
git checkout rama-original
git stash pop

7. Reescritura Profunda con Filter-Branch

git filter-branch es una herramienta poderosa (aunque peligrosa) para reescribir grandes porciones de tu historial:

# Eliminar un archivo de todo el historial (útil para archivos grandes o sensibles)
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD

# Cambiar dirección de correo electrónico en todo el historial
git filter-branch --commit-filter '
    if [ "$GIT_AUTHOR_EMAIL" = "[email protected]" ];
    then
        GIT_AUTHOR_EMAIL="[email protected]";
        git commit-tree "$@";
    else
        git commit-tree "$@";
    fi' HEAD

Advertencia: filter-branch reescribe la historia del repositorio. Nunca lo uses en ramas públicas compartidas.

8. Git Hooks: Automatización a Nivel de Repositorio

Los Git hooks son scripts que Git ejecuta automáticamente antes o después de eventos como commit, push, y receive:

# Los hooks se almacenan en .git/hooks/
# Ejemplo de pre-commit hook para ejecutar tests antes de cada commit

Crea un archivo .git/hooks/pre-commit:

#!/bin/sh
# Ejecutar pruebas antes de permitir un commit
php artisan test

# Si las pruebas fallan, evitar el commit
if [ $? -ne 0 ]; then
  echo "Las pruebas han fallado. Commit abortado."
  exit 1
fi

No olvides hacer el script ejecutable:

chmod +x .git/hooks/pre-commit

Caso práctico: Configurar un hook de pre-push para asegurar que todo el código pasa los linters antes de ser enviado al repositorio remoto:

#!/bin/sh
# .git/hooks/pre-push

echo "Ejecutando análisis de código..."
npm run lint

if [ $? -ne 0 ]; then
  echo "El linting ha fallado. Push abortado."
  exit 1
fi

9. Git Aliases: Workflows Personalizados

Configura aliases para comandos complejos que usas frecuentemente:

# Configurar un alias para ver un log gráfico bonito
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"

# Configurar un alias para deshacer el último commit
git config --global alias.undo "reset HEAD~1 --mixed"

Caso práctico: Crear un alias para gestionar rápidamente cambios entre ramas de feature y desarrollo:

git config --global alias.sync "!f() { git checkout dev && git pull && git checkout - && git rebase dev; }; f"

# Ahora puedes simplemente usar:
git sync

10. Git Rerere (Reuse Recorded Resolution)

git rerere permite a Git recordar cómo resolviste un conflicto específico, para que pueda resolverlo automáticamente la próxima vez que lo encuentre:

# Habilitar rerere
git config --global rerere.enabled true

# Ahora, cuando resuelvas conflictos durante un merge o rebase,
# Git recordará cómo los resolviste

Caso práctico: Estás trabajando en una rama larga que necesita ser rebased frecuentemente con la rama principal. Cada rebase produce los mismos conflictos:

# Con rerere habilitado:
git rebase main

# Resolver conflictos manualmente la primera vez
git add archivo-con-conflictos.js
git rebase --continue

# En futuros rebases, Git resolverá automáticamente
# los mismos conflictos de la misma manera

Conclusión

Dominar estas técnicas avanzadas de Git no solo te hará más eficiente como desarrollador, sino que también te ayudará a mantener un historial de código limpio y a resolver problemas complejos con confianza. Git es una herramienta increíblemente poderosa cuya profundidad va mucho más allá de los comandos básicos que usamos diariamente.

Rutas de aprendizaje