[ADDED] Script backlog.sh para recuperar repositorio o archivos de un commit específico
This commit is contained in:
parent
a5e1cf5787
commit
de26489b2a
2 changed files with 317 additions and 0 deletions
26
README.md
26
README.md
|
@ -100,6 +100,7 @@ MRDevs Tools utiliza una estructura organizada que separa el código (en ~/devs)
|
|||
|
||||
| Comando | Descripción |
|
||||
|---------|-------------|
|
||||
| `bin/backlog.sh <commit_id>` | Revierte el repositorio o archivos específicos al estado de un commit concreto |
|
||||
| `bin/ghadmin_install.sh` | Instala GitHub CLI (gh) con soporte multiplataforma |
|
||||
| `bin/gladmin_install.sh` | Instala GitLab CLI (glab) con múltiples métodos de instalación |
|
||||
| `bin/fjadmin_install.sh` | Instala Forgejo CLI (berg) para administración de Forgejo/Codeberg |
|
||||
|
@ -140,6 +141,31 @@ El directorio `$HOME/devs` sirve como área principal de desarrollo donde se ges
|
|||
|
||||
Si desea usar Docker en lugar de Podman, debe instalarlo manualmente antes de ejecutar `bootstrap.sh`.
|
||||
|
||||
### Gestión Avanzada de Repositorios Git
|
||||
|
||||
```bash
|
||||
# Revertir todo el repositorio a un commit específico
|
||||
bin/backlog.sh a1b2c3d
|
||||
|
||||
# Recuperar solo un archivo específico desde un commit
|
||||
bin/backlog.sh a1b2c3d --file src/config.js
|
||||
|
||||
# Recuperar múltiples archivos usando un patrón
|
||||
bin/backlog.sh a1b2c3d --files "*.js"
|
||||
|
||||
# Ver solo la lista de archivos modificados en un commit
|
||||
bin/backlog.sh a1b2c3d --list
|
||||
|
||||
# Ver la ayuda completa del comando
|
||||
bin/backlog.sh --help
|
||||
```
|
||||
|
||||
El script `backlog.sh` permite recuperar estados previos del repositorio con varias opciones de seguridad:
|
||||
- Crea ramas de respaldo automáticamente antes de realizar cambios
|
||||
- Ofrece guardar cambios no confirmados en stash
|
||||
- Proporciona confirmaciones interactivas antes de acciones potencialmente destructivas
|
||||
- Incluye instrucciones para deshacer los cambios si fuera necesario
|
||||
|
||||
### Configuración de Herramientas de IA
|
||||
|
||||
MRDevs Tools facilita el trabajo con herramientas de IA:
|
||||
|
|
291
bin/backlog.sh
Executable file
291
bin/backlog.sh
Executable file
|
@ -0,0 +1,291 @@
|
|||
#!/bin/bash
|
||||
#Script : backlog.sh
|
||||
#Apps : MRDEVS TOOLS
|
||||
#Description : Revierte el repositorio o archivos específicos al estado de un commit
|
||||
#Author : Cortana Rosero One <cortana@rosero.one>
|
||||
#Company Email : mauro@rosero.one
|
||||
#Personal Email : cortana@rosero.one
|
||||
#Created : 2025-04-01 10:00:00
|
||||
#Modified : 2025-04-01 11:30:00
|
||||
#Version : 1.3.1
|
||||
#Use Notes : ./backlog.sh <commit_id> [--file <archivo>] [--files <patrón>]
|
||||
#==============================================================================
|
||||
# Derechos de Autor 2025 Mauro Rosero P. <mauro@rosero.one>
|
||||
#==============================================================================
|
||||
# Este programa es software libre: usted puede redistribuirlo y/o modificarlo
|
||||
# bajo los términos de la Licencia Pública Affero General de GNU tal como
|
||||
# lo publica la Free Software Foundation, ya sea la versión 3 de la licencia,
|
||||
# o (a su elección) cualquier versión posterior.
|
||||
#
|
||||
# Este programa se distribuye con la esperanza de que sea útil,
|
||||
# pero SIN NINGUNA GARANTÍA; sin siquiera la garantía implícita de
|
||||
# COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la
|
||||
# Licencia Pública Affero General de GNU para obtener más detalles.
|
||||
#
|
||||
# Debería haber recibido una copia de la Licencia Pública Affero General
|
||||
# junto con este programa. Si no la recibió, consulte <https://www.gnu.org/licenses/>.
|
||||
|
||||
# Definir variables básicas
|
||||
BIN_HOME=${HOME}/devs
|
||||
BIN_BASE=bin
|
||||
|
||||
# Mostrar ayuda
|
||||
function mostrar_ayuda {
|
||||
echo "Uso: $0 <commit_id> [opciones]"
|
||||
echo ""
|
||||
echo "Opciones:"
|
||||
echo " --full Revierte todo el repositorio al commit especificado (por defecto)"
|
||||
echo " --file <archivo> Revierte un archivo específico al estado del commit"
|
||||
echo " --files <patrón> Revierte archivos que coincidan con un patrón"
|
||||
echo " --list Lista los archivos modificados en el commit sin revertir nada"
|
||||
echo " --help Muestra esta ayuda"
|
||||
echo ""
|
||||
echo "Ejemplos:"
|
||||
echo " $0 abc123 # Revierte todo el repositorio al commit abc123"
|
||||
echo " $0 abc123 --file src/main.js # Revierte solo src/main.js al estado del commit abc123"
|
||||
echo " $0 abc123 --files \"*.js\" # Revierte todos los archivos .js al estado del commit abc123"
|
||||
echo " $0 abc123 --list # Muestra los archivos que cambiaron en el commit abc123"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Verificar si hay suficientes parámetros
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "Error: Se requiere un commit_id como parámetro."
|
||||
mostrar_ayuda
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Inicializar variables
|
||||
COMMIT_ID="$1"
|
||||
shift
|
||||
MODO="full"
|
||||
ARCHIVO=""
|
||||
PATRON=""
|
||||
|
||||
# Procesar argumentos adicionales
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--help)
|
||||
mostrar_ayuda
|
||||
;;
|
||||
--full)
|
||||
MODO="full"
|
||||
;;
|
||||
--file)
|
||||
MODO="file"
|
||||
ARCHIVO="$2"
|
||||
if [ -z "$ARCHIVO" ]; then
|
||||
echo "Error: Falta el nombre del archivo después de --file"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
--files)
|
||||
MODO="files"
|
||||
PATRON="$2"
|
||||
if [ -z "$PATRON" ]; then
|
||||
echo "Error: Falta el patrón después de --files"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
--list)
|
||||
MODO="list"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Opción desconocida: $1"
|
||||
mostrar_ayuda
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Verificar si estamos en un repositorio git
|
||||
if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
|
||||
echo "Error: Este comando debe ejecutarse dentro de un repositorio git."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificar si el commit_id existe
|
||||
if ! git rev-parse --verify "$COMMIT_ID^{commit}" >/dev/null 2>&1; then
|
||||
echo "Error: El commit_id '$COMMIT_ID' no existe en este repositorio."
|
||||
echo "Buscando referencias a ese commit_id..."
|
||||
|
||||
# Intentar encontrar commits parciales
|
||||
POSIBLES_COMMITS=$(git log --all --pretty=format:"%h %s" | grep -i "$COMMIT_ID")
|
||||
if [ -n "$POSIBLES_COMMITS" ]; then
|
||||
echo "Posibles coincidencias encontradas:"
|
||||
echo "$POSIBLES_COMMITS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "No se encontraron referencias al commit proporcionado."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Si el modo es "list", mostrar los archivos modificados y salir
|
||||
if [ "$MODO" = "list" ]; then
|
||||
echo "📋 Archivos modificados en el commit $COMMIT_ID:"
|
||||
git show --name-status "$COMMIT_ID" | grep -E "^[AMD]" | sort
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Verificar si hay cambios sin confirmar
|
||||
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||
echo "⚠️ ADVERTENCIA: Hay cambios sin confirmar en tu repositorio."
|
||||
if [ "$MODO" = "full" ]; then
|
||||
echo "Estos cambios se perderán si continúas con la reversión completa."
|
||||
else
|
||||
echo "Estos cambios podrían causar conflictos con los archivos que intentas recuperar."
|
||||
fi
|
||||
read -p "¿Deseas guardar estos cambios en un stash? (s/n): " respuesta
|
||||
|
||||
if [[ "$respuesta" == "s" || "$respuesta" == "S" ]]; then
|
||||
STASH_NAME="stash_before_reset_to_${COMMIT_ID}_$(date +%Y%m%d_%H%M%S)"
|
||||
git stash push -m "$STASH_NAME"
|
||||
echo "Cambios guardados en stash: $STASH_NAME"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Crear una rama de respaldo antes de hacer cualquier cambio (si es reversión completa)
|
||||
if [ "$MODO" = "full" ]; then
|
||||
CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse HEAD)
|
||||
BACKUP_BRANCH="backup_${CURRENT_BRANCH}_before_reset_$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
echo "Creando rama de respaldo '$BACKUP_BRANCH'..."
|
||||
git branch "$BACKUP_BRANCH"
|
||||
|
||||
# Obtener información del commit para el resumen
|
||||
COMMIT_INFO=$(git show --quiet --format="%h - %s (%an, %ad)" --date=format:"%Y-%m-%d %H:%M:%S" "$COMMIT_ID")
|
||||
echo "⚠️ ADVERTENCIA: Estás a punto de revertir TODO el repositorio al commit:"
|
||||
echo "$COMMIT_INFO"
|
||||
echo "Todos los cambios posteriores a este commit se perderán."
|
||||
echo "Se ha creado una rama de respaldo: $BACKUP_BRANCH"
|
||||
|
||||
read -p "¿Estás seguro de que quieres continuar? (s/n): " confirmacion
|
||||
if [[ "$confirmacion" != "s" && "$confirmacion" != "S" ]]; then
|
||||
echo "Operación cancelada por el usuario."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Revirtiendo todo el repositorio al commit $COMMIT_ID..."
|
||||
|
||||
# Realizar la reversión usando reset (se perderán todos los cambios locales)
|
||||
git reset --hard "$COMMIT_ID"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Repositorio revertido exitosamente al commit: $COMMIT_ID"
|
||||
echo "Información del commit:"
|
||||
git show --quiet --format="%h - %s%n%nAutor: %an <%ae>%nFecha: %ad%n%n%b" --date=format:"%Y-%m-%d %H:%M:%S" "$COMMIT_ID"
|
||||
echo ""
|
||||
echo "Para recuperar los cambios anteriores, puedes usar la rama de respaldo:"
|
||||
echo " git checkout $BACKUP_BRANCH"
|
||||
echo ""
|
||||
echo "Si necesitas empujar este cambio a un repositorio remoto, usa:"
|
||||
echo " git push --force origen $CURRENT_BRANCH"
|
||||
echo ""
|
||||
echo "⚠️ ADVERTENCIA: El uso de git push --force puede causar problemas en repositorios compartidos."
|
||||
else
|
||||
echo "❌ Error al revertir al commit $COMMIT_ID"
|
||||
echo "Puedes intentar manualmente con:"
|
||||
echo " git reset --hard $COMMIT_ID"
|
||||
fi
|
||||
elif [ "$MODO" = "file" ]; then
|
||||
# Verificar si el archivo existía en el commit
|
||||
if ! git ls-tree -r "$COMMIT_ID" --name-only | grep -q "^$ARCHIVO$"; then
|
||||
echo "⚠️ El archivo '$ARCHIVO' no existía en el commit $COMMIT_ID o la ruta es incorrecta."
|
||||
echo "Archivos disponibles en ese commit que coinciden parcialmente:"
|
||||
git ls-tree -r "$COMMIT_ID" --name-only | grep -i "$(basename "$ARCHIVO")"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Recuperando el archivo '$ARCHIVO' desde el commit $COMMIT_ID..."
|
||||
|
||||
# Crear directorio temporal
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
# Extraer el archivo del commit
|
||||
git show "$COMMIT_ID:$ARCHIVO" > "$TEMP_DIR/$(basename "$ARCHIVO")" 2>/dev/null
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Error al recuperar el archivo del commit."
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Crear directorio para el archivo si no existe
|
||||
ARCHIVO_DIR=$(dirname "$ARCHIVO")
|
||||
if [ "$ARCHIVO_DIR" != "." ] && [ ! -d "$ARCHIVO_DIR" ]; then
|
||||
mkdir -p "$ARCHIVO_DIR"
|
||||
fi
|
||||
|
||||
# Copiar el archivo de vuelta a su ubicación
|
||||
cp "$TEMP_DIR/$(basename "$ARCHIVO")" "$ARCHIVO"
|
||||
|
||||
# Limpiar
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
echo "✅ Archivo '$ARCHIVO' recuperado exitosamente desde el commit $COMMIT_ID."
|
||||
echo "Para confirmar estos cambios, usa:"
|
||||
echo " git add \"$ARCHIVO\""
|
||||
echo " git commit -m \"Recuperado $ARCHIVO desde el commit $COMMIT_ID\""
|
||||
elif [ "$MODO" = "files" ]; then
|
||||
# Obtener la lista de archivos que coinciden con el patrón en el commit
|
||||
ARCHIVOS_COINCIDENTES=$(git ls-tree -r "$COMMIT_ID" --name-only | grep -E "$PATRON" || echo "")
|
||||
|
||||
if [ -z "$ARCHIVOS_COINCIDENTES" ]; then
|
||||
echo "❌ No se encontraron archivos que coincidan con el patrón '$PATRON' en el commit $COMMIT_ID."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Se encontraron $(echo "$ARCHIVOS_COINCIDENTES" | wc -l) archivos que coinciden con el patrón '$PATRON':"
|
||||
echo "$ARCHIVOS_COINCIDENTES" | sed 's/^/ - /'
|
||||
|
||||
read -p "¿Quieres recuperar todos estos archivos? (s/n): " confirmacion
|
||||
if [[ "$confirmacion" != "s" && "$confirmacion" != "S" ]]; then
|
||||
echo "Operación cancelada por el usuario."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Crear directorio temporal
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
# Recuperar cada archivo
|
||||
CONTADOR_EXITO=0
|
||||
CONTADOR_ERROR=0
|
||||
|
||||
echo "$ARCHIVOS_COINCIDENTES" | while read -r archivo; do
|
||||
# Crear la estructura de directorios necesaria
|
||||
mkdir -p "$TEMP_DIR/$(dirname "$archivo")"
|
||||
|
||||
# Extraer el archivo del commit
|
||||
git show "$COMMIT_ID:$archivo" > "$TEMP_DIR/$archivo" 2>/dev/null
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
# Crear directorio para el archivo si no existe
|
||||
ARCHIVO_DIR=$(dirname "$archivo")
|
||||
if [ "$ARCHIVO_DIR" != "." ] && [ ! -d "$ARCHIVO_DIR" ]; then
|
||||
mkdir -p "$ARCHIVO_DIR"
|
||||
fi
|
||||
|
||||
# Copiar el archivo de vuelta a su ubicación
|
||||
cp "$TEMP_DIR/$archivo" "$archivo"
|
||||
echo "✅ Recuperado: $archivo"
|
||||
CONTADOR_EXITO=$((CONTADOR_EXITO + 1))
|
||||
else
|
||||
echo "❌ Error al recuperar: $archivo"
|
||||
CONTADOR_ERROR=$((CONTADOR_ERROR + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Limpiar
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
echo "Recuperación finalizada: $CONTADOR_EXITO archivos recuperados, $CONTADOR_ERROR errores."
|
||||
echo "Para confirmar estos cambios, usa:"
|
||||
echo " git add -A"
|
||||
echo " git commit -m \"Recuperados archivos $PATRON desde el commit $COMMIT_ID\""
|
||||
fi
|
||||
|
||||
exit 0
|
Loading…
Reference in a new issue