Files
fn_registry/bash/functions/shell/git_clean_branches.sh
T
egutierrez 8f45b40528 feat: add bash shell utility functions
12 funciones Bash del dominio shell: utilidades de scripting (bash_log,
bash_colors, bash_check_deps, bash_confirm, bash_handle_error, bash_safe_run),
manipulacion de texto (convert_text_case), estructura de proyectos
(create_project_structure), y operaciones git (git_clean_branches,
git_log_visual, git_push_all_remotes, git_repo_status). Cada una con su
.sh y .md de frontmatter.
2026-04-12 13:54:15 +02:00

127 lines
3.9 KiB
Bash

#!/usr/bin/env bash
# git_clean_branches
# ------------------
# Elimina ramas locales ya mergeadas en la rama base (main/master por defecto).
# Opcionalmente también elimina las ramas en remotes.
#
# USO:
# source git_clean_branches.sh
# git_clean_branches [base_branch] [--remote] [--force]
#
# ARGUMENTOS:
# base_branch Rama base (opcional; autodetecta main/master si se omite)
# --remote Elimina también las ramas en todos los remotes
# --force Omite confirmación interactiva
git_clean_branches() {
local base_branch=""
local delete_remote=false
local force=false
# Parsear argumentos
for arg in "$@"; do
case "$arg" in
--remote) delete_remote=true ;;
--force) force=true ;;
*) [[ -z "$base_branch" ]] && base_branch="$arg" ;;
esac
done
# Validar repo
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
echo "git_clean_branches: el directorio actual no es un repositorio Git" >&2
return 1
fi
# Detectar rama base
if [[ -z "$base_branch" ]]; then
if git show-ref --verify --quiet refs/heads/main; then
base_branch="main"
elif git show-ref --verify --quiet refs/heads/master; then
base_branch="master"
else
echo "git_clean_branches: no se detectó main/master; pasa la rama base como argumento" >&2
return 1
fi
fi
echo "git_clean_branches: rama base = ${base_branch}"
# Hacer prune de referencias remotas obsoletas
echo "Haciendo prune de referencias remotas..."
git remote | while IFS= read -r remote; do
git remote prune "$remote" 2>/dev/null && echo " Pruned: ${remote}"
done
echo ""
# Buscar ramas locales mergeadas
local candidates
candidates="$(git branch --merged "$base_branch" \
| grep -v -E "^\*|^\s*(main|master|develop|dev|staging|release)$" \
| sed 's/^[[:space:]]*//' \
| grep -v "^$" || true)"
if [[ -z "$candidates" ]]; then
echo "No hay ramas locales mergeadas para eliminar."
return 0
fi
echo "Ramas candidatas a eliminar:"
echo "$candidates" | while IFS= read -r b; do
echo " - ${b}"
done
echo ""
# Confirmación (omitir si --force)
if [[ "$force" != true ]]; then
echo -n "¿Eliminar estas ramas locales? [y/N] "
read -r answer
[[ "$answer" != "y" && "$answer" != "Y" ]] && { echo "Operación cancelada."; return 0; }
fi
# Eliminar ramas locales
local deleted=0
local failed=0
while IFS= read -r branch; do
if git branch -d "$branch"; then
echo " Eliminada local: ${branch}"
deleted=$((deleted + 1))
else
echo " No se pudo eliminar: ${branch}" >&2
failed=$((failed + 1))
fi
done <<< "$candidates"
echo ""
echo "Resumen: ${deleted} eliminada(s), ${failed} fallida(s)"
# Eliminar en remotes si se solicitó
if [[ "$delete_remote" == true ]]; then
local remotes
remotes="$(git remote 2>/dev/null || true)"
if [[ -n "$remotes" ]]; then
echo ""
echo "Eliminando ramas en remotes..."
while IFS= read -r branch; do
while IFS= read -r remote; do
if git ls-remote --heads "$remote" "$branch" 2>/dev/null | grep -q "$branch"; then
if git push "$remote" --delete "$branch"; then
echo " Eliminada remota: ${remote}/${branch}"
else
echo " No se pudo eliminar remota: ${remote}/${branch}" >&2
fi
fi
done <<< "$remotes"
done <<< "$candidates"
fi
fi
echo ""
echo "Limpieza completada."
}
# Ejecutar si se invoca directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
git_clean_branches "$@"
fi