10 KiB
Command: git-recovery
Recupera el repositorio de estados inconsistentes causados por worktrees huérfanos, branches bloqueados o conflictos de git. Ejecuta automáticamente cuando se detectan errores git durante operaciones de issues.
Para el usuario
Cuándo usar este comando
- Cuando hay errores "exit status 128" al crear worktrees
- Cuando git reporta "worktree already exists"
- Cuando hay branches que no se pueden eliminar
- Cuando
git worktree listmuestra worktrees huérfanos - Cuando el orquestador paralelo falla por problemas git
- Automáticamente: El sistema lo invoca cuando detecta errores git
Sintaxis
/git:recovery [--aggressive]
Parámetros
--aggressive(opcional): Fuerza limpieza agresiva incluyendo branches remotas y reset de estado
Ejemplos
Ejemplo 1: Recuperación estándar (recomendado)
/git:recovery
Limpia worktrees huérfanos, verifica estado, sincroniza con remoto.
Ejemplo 2: Recuperación agresiva
/git:recovery --aggressive
Incluye force-prune, eliminación de branches huérfanas, reset de índice.
Para Claude
Precondiciones
Verificar antes de ejecutar:
- Estamos en un repositorio git válido
- Hay permisos para modificar .git/
- No hay operaciones git críticas en progreso (rebase, merge)
Inputs
--aggressive(opcional): Modo agresivo de limpieza
Flujo obligatorio
1. Diagnóstico inicial
echo "🔍 Diagnosticando estado del repositorio..."
echo ""
# Verificar que estamos en repo git
if [ ! -d ".git" ]; then
echo "❌ Error: No estamos en un repositorio git"
exit 1
fi
# Guardar estado actual
git branch --show-current > /tmp/git-recovery-current-branch.txt
git status --porcelain > /tmp/git-recovery-status.txt
echo "Rama actual: $(cat /tmp/git-recovery-current-branch.txt)"
echo "Cambios pendientes: $(wc -l < /tmp/git-recovery-status.txt) archivos"
echo ""
2. Análisis de problemas
echo "📋 Analizando problemas..."
echo ""
# Listar worktrees (puede fallar si hay huérfanos)
echo "Worktrees actuales:"
git worktree list 2>&1 || echo " (error listando worktrees - probablemente hay huérfanos)"
echo ""
# Verificar branches locales
echo "Branches locales:"
git branch --list
echo ""
# Verificar branches remotas
echo "Estado remoto:"
git remote -v
git fetch --dry-run 2>&1 || echo " (problemas con fetch)"
echo ""
3. Limpieza de worktrees huérfanos
echo "🧹 Limpiando worktrees huérfanos..."
echo ""
# Ejecutar prune (elimina referencias a worktrees que ya no existen)
git worktree prune -v 2>&1
# Verificar si aún hay worktrees huérfanos en disco
if [ -d "worktrees" ]; then
echo ""
echo "Verificando directorio worktrees/..."
# Listar directorios en worktrees/
for worktree_dir in worktrees/issue-*; do
if [ -d "$worktree_dir" ]; then
worktree_name=$(basename "$worktree_dir")
# Verificar si git lo conoce
if ! git worktree list | grep -q "$worktree_dir"; then
echo " ⚠️ Worktree huérfano detectado: $worktree_name"
# Eliminar directorio huérfano
rm -rf "$worktree_dir"
echo " ✓ Eliminado: $worktree_dir"
fi
fi
done
fi
echo ""
echo "✓ Limpieza de worktrees completada"
echo ""
4. Verificación de branches bloqueados
echo "🔓 Verificando branches bloqueados..."
echo ""
# Listar branches que podrían estar bloqueados
git branch --list 'issue/*' 'quick/*' | while read -r branch; do
branch=$(echo "$branch" | sed 's/^\* //' | xargs)
# Verificar si la branch está asociada a un worktree
if git worktree list | grep -q "$branch"; then
echo " ℹ️ Branch activa en worktree: $branch"
else
# Branch no está en worktree, podría estar mergeada
if git branch --merged master | grep -q "$branch"; then
echo " ✓ Branch mergeada, puede eliminarse: $branch"
git branch -d "$branch" 2>&1 || echo " (no se pudo eliminar automáticamente)"
else
echo " ⚠️ Branch NO mergeada: $branch"
fi
fi
done
echo ""
5. Sincronización con remoto
echo "🔄 Sincronizando con remoto..."
echo ""
# Volver a master si no estamos ahí
current_branch=$(git branch --show-current)
if [ "$current_branch" != "master" ]; then
echo "Cambiando a master desde $current_branch..."
git checkout master 2>&1 || {
echo "❌ No se pudo cambiar a master"
echo " Quedando en rama: $current_branch"
}
fi
# Fetch y pull
echo "Actualizando desde origin/master..."
git fetch origin 2>&1
git pull --rebase origin master 2>&1 || {
echo "⚠️ Problemas al hacer pull, continuando..."
}
echo ""
echo "✓ Sincronización completada"
echo ""
6. Modo agresivo (solo si --aggressive)
if [ "$AGGRESSIVE" = "true" ]; then
echo "⚡ MODO AGRESIVO ACTIVADO"
echo ""
echo "Limpiando branches remotas obsoletas..."
git remote prune origin -v 2>&1
echo ""
echo "Verificando integridad del repositorio..."
git fsck --full 2>&1 | head -20
echo ""
echo "Limpiando objetos no referenciados..."
git gc --prune=now 2>&1
echo ""
echo "Verificando índice..."
if [ -f ".git/index.lock" ]; then
echo " ⚠️ Encontrado index.lock (proceso git interrumpido)"
rm -f .git/index.lock
echo " ✓ Eliminado .git/index.lock"
fi
echo ""
echo "✓ Limpieza agresiva completada"
echo ""
fi
7. Verificación final
echo "✅ Verificación final..."
echo ""
# Estado limpio
echo "Estado del repositorio:"
git status
echo ""
# Worktrees finales
echo "Worktrees activos:"
git worktree list
echo ""
# Branches locales
echo "Branches locales:"
git branch --list
echo ""
8. Resumen
echo "════════════════════════════════════════════════════════"
echo "RECUPERACIÓN COMPLETADA"
echo "════════════════════════════════════════════════════════"
echo ""
# Comparar estado antes/después
CHANGES_BEFORE=$(wc -l < /tmp/git-recovery-status.txt)
CHANGES_AFTER=$(git status --porcelain | wc -l)
echo "Resumen:"
echo " Rama actual: $(git branch --show-current)"
echo " Cambios pendientes: $CHANGES_AFTER (antes: $CHANGES_BEFORE)"
echo " Worktrees activos: $(git worktree list | grep -v bare | wc -l)"
echo " Sincronizado con origin: $(git rev-parse HEAD) = $(git rev-parse origin/master 2>/dev/null || echo 'N/A')"
echo ""
if [ "$AGGRESSIVE" = "true" ]; then
echo "Modo agresivo aplicado: ✓"
echo ""
fi
echo "Próximos pasos:"
echo " - Verifica que master esté actualizado: git log --oneline -5"
echo " - Reintenta la operación que falló"
echo " - Si persisten errores, reporta el problema"
echo ""
# Limpiar archivos temporales
rm -f /tmp/git-recovery-*.txt
Detección automática de errores git
El orquestador Go debe detectar estos patrones de error:
Patrones de error que activan recovery:
exit status 128(error genérico de git)worktree .* already existsreference is not a treecannot lock refindex.lockfatal: not a git repository
Flujo de auto-recovery:
- Orquestador detecta error git
- Pausa ejecución del grupo actual
- Ejecuta
claude -p /git:recoveryautomáticamente - Si recovery tiene éxito (exit code 0), reintenta la operación
- Si recovery falla, aborta con error descriptivo
Verificación final
# Verificar que el repo quedó en estado válido
git status --porcelain
git worktree list
# Exit code 0 si todo OK, 1 si hay problemas
if [ $? -eq 0 ]; then
exit 0
else
echo "❌ El repositorio sigue con problemas"
exit 1
fi
Convenciones
- No destructivo por defecto: Solo limpia worktrees huérfanos y branches mergeadas
- Modo agresivo bajo demanda: Solo con flag explícito
- Siempre sincroniza con remoto: Garantiza consistencia
- Preserva cambios locales: No hace reset hard sin --aggressive
- Logs detallados: Reporta cada acción para debugging
Troubleshooting
Error: "cannot remove worktree"
Causa: Proceso usando archivos del worktree
Solución:
# Verificar procesos
lsof +D worktrees/ 2>/dev/null
# Forzar eliminación con --aggressive
/git:recovery --aggressive
Error: "index.lock exists"
Causa: Operación git previa interrumpida
Solución: Automáticamente manejado en modo estándar. Si persiste:
rm -f .git/index.lock
/git:recovery
Warning: "branch no mergeada"
Causa: Branch contiene commits no integrados a master
Solución: Verificar manualmente si es seguro eliminarla:
git log master..branch-name
git branch -D branch-name # Solo si estás seguro
Reglas críticas
- NUNCA hacer git reset --hard sin --aggressive - puede perder cambios
- SIEMPRE hacer backup del estado antes de recovery agresivo
- NUNCA eliminar branches no mergeadas automáticamente
- SIEMPRE sincronizar con remoto después de limpieza
- SIEMPRE verificar que quedó en estado válido
- LOGS completos - reportar cada acción para auditoría
Integración con orquestador
El orquestador Go debe:
- Capturar stderr de comandos git
- Detectar patrones de error conocidos
- Invocar recovery automáticamente:
if isGitError(err) { log.Warn("Error git detectado, ejecutando recovery...") if err := executeRecovery(); err != nil { return fmt.Errorf("recovery falló: %w", err) } // Reintentar operación original return retryOperation() } - Limitar reintentos a 1 vez por operación
- Abortar si recovery falla
Ejemplos de uso automático
Escenario 1: Error al crear worktree
[ERROR] crear worktree: exit status 128
[INFO] Detectado error git, ejecutando recovery...
[INFO] ✓ Recovery completado
[INFO] Reintentando crear worktree...
[SUCCESS] ✓ Worktree creado exitosamente
Escenario 2: Recovery falla
[ERROR] crear worktree: exit status 128
[INFO] Detectado error git, ejecutando recovery...
[ERROR] Recovery falló: problemas persistentes
[ABORT] Abortando ejecución del grupo