8f45b40528
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.
128 lines
3.6 KiB
Bash
128 lines
3.6 KiB
Bash
#!/usr/bin/env bash
|
|
# git_push_all_remotes
|
|
# --------------------
|
|
# Hace commit de todos los cambios pendientes (si los hay) y pushea
|
|
# a todos los remotes configurados en el repositorio.
|
|
#
|
|
# USO:
|
|
# source git_push_all_remotes.sh
|
|
# git_push_all_remotes [--message "mensaje"]
|
|
#
|
|
# ARGUMENTOS:
|
|
# --message "msg" Mensaje de commit (si hay cambios). Si se omite y hay
|
|
# cambios, sale con error.
|
|
|
|
git_push_all_remotes() {
|
|
local commit_msg=""
|
|
|
|
# Parsear argumentos
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--message|-m)
|
|
commit_msg="$2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Validar repo
|
|
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
|
|
echo "git_push_all_remotes: el directorio actual no es un repositorio Git" >&2
|
|
return 1
|
|
fi
|
|
|
|
local branch
|
|
branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
|
|
|
|
local remotes
|
|
remotes="$(git remote 2>/dev/null || true)"
|
|
|
|
if [[ -z "$remotes" ]]; then
|
|
echo "git_push_all_remotes: no hay remotes configurados en este repositorio" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "Rama actual: ${branch}"
|
|
echo "Remotes:"
|
|
echo "$remotes" | while IFS= read -r r; do
|
|
local url
|
|
url="$(git remote get-url "$r" 2>/dev/null || echo "?")"
|
|
echo " ${r} → ${url}"
|
|
done
|
|
echo ""
|
|
|
|
# Gestión del commit si hay cambios
|
|
local has_changes=false
|
|
if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then
|
|
has_changes=true
|
|
fi
|
|
|
|
if [[ "$has_changes" == true ]]; then
|
|
if [[ -z "$commit_msg" ]]; then
|
|
echo "git_push_all_remotes: hay cambios pero no se proporcionó --message" >&2
|
|
echo " Usa: git_push_all_remotes --message \"tu mensaje\"" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "Cambios detectados:"
|
|
git status --short | while IFS= read -r line; do
|
|
echo " ${line}"
|
|
done
|
|
echo ""
|
|
|
|
echo "Añadiendo todos los cambios..."
|
|
git add -A
|
|
|
|
echo "Haciendo commit: \"${commit_msg}\""
|
|
git commit -m "$commit_msg"
|
|
echo ""
|
|
else
|
|
echo "Directorio de trabajo limpio. Se empujarán commits existentes."
|
|
echo ""
|
|
fi
|
|
|
|
# Push a cada remote
|
|
local ok_count=0
|
|
local fail_count=0
|
|
local failed_remotes=()
|
|
local remote_count
|
|
remote_count="$(echo "$remotes" | wc -l | tr -d ' ')"
|
|
|
|
while IFS= read -r remote; do
|
|
# Verificar si la rama existe en el remote
|
|
local push_flags=""
|
|
if ! git ls-remote --heads "$remote" "$branch" 2>/dev/null | grep -q "$branch"; then
|
|
push_flags="--set-upstream"
|
|
echo "La rama '${branch}' no existe en '${remote}', se creará"
|
|
fi
|
|
|
|
echo "Push → ${remote} (${branch})..."
|
|
# shellcheck disable=SC2086
|
|
if git push $push_flags "$remote" "$branch" 2>&1; then
|
|
echo " Push completado → ${remote}/${branch}"
|
|
ok_count=$((ok_count + 1))
|
|
else
|
|
echo " Falló el push a ${remote}/${branch}" >&2
|
|
fail_count=$((fail_count + 1))
|
|
failed_remotes+=("$remote")
|
|
fi
|
|
echo ""
|
|
done <<< "$remotes"
|
|
|
|
echo "=== Resumen ==="
|
|
echo "Push completado en ${ok_count}/${remote_count} remote(s)"
|
|
|
|
if [[ $fail_count -gt 0 ]]; then
|
|
echo "Fallaron ${fail_count} remote(s): ${failed_remotes[*]}" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Ejecutar si se invoca directamente
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
git_push_all_remotes "$@"
|
|
fi
|