#!/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