git-sync-all.sh: Repos klonen, pullen und pushen in einem Befehl
This commit is contained in:
parent
8668d95bd4
commit
dfc21f4cfa
1 changed files with 190 additions and 0 deletions
190
bin/git-sync-all.sh
Executable file
190
bin/git-sync-all.sh
Executable file
|
|
@ -0,0 +1,190 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
BASE_DIR="${BASE_DIR:-$HOME/git-projekte}"
|
||||||
|
GITEA_BASE="https://git.motocamp.de/rene"
|
||||||
|
|
||||||
|
# Alle Repos auf dem Gitea-Server.
|
||||||
|
# Bei neuen Repos hier einen Eintrag ergaenzen.
|
||||||
|
REPO_NAMES=(
|
||||||
|
balkonsteuerung
|
||||||
|
berechnungstabellen
|
||||||
|
claude-skills
|
||||||
|
comfy
|
||||||
|
dotfiles-rene
|
||||||
|
esp32
|
||||||
|
ki-agenten
|
||||||
|
macbook-setup
|
||||||
|
Pi_pico_2w
|
||||||
|
portainer
|
||||||
|
skripte
|
||||||
|
test
|
||||||
|
web
|
||||||
|
zellenhalter-generator
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- Farben ----------------------------------------------------------------
|
||||||
|
if [ -t 1 ]; then
|
||||||
|
C_RED=$'\033[31m'
|
||||||
|
C_GREEN=$'\033[32m'
|
||||||
|
C_YELLOW=$'\033[33m'
|
||||||
|
C_CYAN=$'\033[36m'
|
||||||
|
C_BOLD=$'\033[1m'
|
||||||
|
C_RESET=$'\033[0m'
|
||||||
|
else
|
||||||
|
C_RED=""; C_GREEN=""; C_YELLOW=""; C_CYAN=""; C_BOLD=""; C_RESET=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Argumente -------------------------------------------------------------
|
||||||
|
DRY_RUN=false
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-p|--path) BASE_DIR="$2"; shift 2 ;;
|
||||||
|
-n|--dry-run) DRY_RUN=true; shift ;;
|
||||||
|
-h|--help)
|
||||||
|
cat <<EOF
|
||||||
|
Usage: ${0##*/} [OPTIONEN]
|
||||||
|
|
||||||
|
Synchronisiert alle Git-Repositories mit dem Gitea-Server:
|
||||||
|
- Fehlende Repos werden geklont
|
||||||
|
- Repos mit Remote-Aenderungen werden gepullt
|
||||||
|
- Repos mit lokalen Commits werden gepusht
|
||||||
|
- Repos mit uncommitteten Aenderungen werden markiert
|
||||||
|
|
||||||
|
Optionen:
|
||||||
|
-p, --path DIR anderes Basisverzeichnis statt ~/git-projekte
|
||||||
|
-n, --dry-run nur anzeigen, nichts aendern
|
||||||
|
-h, --help diese Hilfe anzeigen
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*) echo "Unbekannte Option: $1" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p "$BASE_DIR"
|
||||||
|
|
||||||
|
echo "${C_BOLD}Git-Sync: $BASE_DIR${C_RESET}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# --- Zaehler ---------------------------------------------------------------
|
||||||
|
total=0
|
||||||
|
cloned=0
|
||||||
|
pulled=0
|
||||||
|
pushed=0
|
||||||
|
dirty=0
|
||||||
|
uptodate=0
|
||||||
|
failed=0
|
||||||
|
|
||||||
|
# --- Repos durchgehen ------------------------------------------------------
|
||||||
|
for NAME in "${REPO_NAMES[@]}"; do
|
||||||
|
URL="${GITEA_BASE}/${NAME}.git"
|
||||||
|
TARGET="$BASE_DIR/$NAME"
|
||||||
|
((total++))
|
||||||
|
|
||||||
|
# 1) Repo fehlt -> klonen
|
||||||
|
if [ ! -d "$TARGET/.git" ]; then
|
||||||
|
if [ -d "$TARGET" ]; then
|
||||||
|
printf "${C_YELLOW}SKIP${C_RESET} %-25s Verzeichnis existiert, kein Git-Repo\n" "$NAME"
|
||||||
|
((failed++))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if $DRY_RUN; then
|
||||||
|
printf "${C_CYAN}CLONE${C_RESET} %-25s (dry-run)\n" "$NAME"
|
||||||
|
else
|
||||||
|
if git clone --quiet "$URL" "$TARGET" 2>/dev/null; then
|
||||||
|
printf "${C_CYAN}CLONE${C_RESET} %-25s geklont\n" "$NAME"
|
||||||
|
((cloned++))
|
||||||
|
else
|
||||||
|
printf "${C_RED}FAIL${C_RESET} %-25s Klonen fehlgeschlagen\n" "$NAME"
|
||||||
|
((failed++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ab hier: Repo existiert
|
||||||
|
cd "$TARGET" || continue
|
||||||
|
|
||||||
|
# Remote fetch
|
||||||
|
git fetch --quiet 2>/dev/null || true
|
||||||
|
|
||||||
|
# 2) Uncommittete Aenderungen?
|
||||||
|
has_changes=false
|
||||||
|
if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then
|
||||||
|
has_changes=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3) Ahead/Behind
|
||||||
|
ahead=0
|
||||||
|
behind=0
|
||||||
|
upstream_info="$(git rev-list --left-right --count "@{u}...HEAD" 2>/dev/null || true)"
|
||||||
|
if [[ -n "$upstream_info" ]]; then
|
||||||
|
read -r behind ahead <<<"$upstream_info"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4) Aktionen
|
||||||
|
did_something=false
|
||||||
|
|
||||||
|
# Pull wenn behind
|
||||||
|
if ((behind > 0)); then
|
||||||
|
if $has_changes; then
|
||||||
|
printf "${C_YELLOW}DIRTY${C_RESET} %-25s %d neue Remote-Commits + lokale Aenderungen\n" "$NAME" "$behind"
|
||||||
|
((dirty++))
|
||||||
|
if ((ahead > 0)); then
|
||||||
|
printf " %-25s + %d lokale Commits nicht gepusht\n" "" "$ahead"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if $DRY_RUN; then
|
||||||
|
printf "${C_GREEN}PULL${C_RESET} %-25s %d Commits (dry-run)\n" "$NAME" "$behind"
|
||||||
|
else
|
||||||
|
if git pull --ff-only --quiet 2>/dev/null; then
|
||||||
|
printf "${C_GREEN}PULL${C_RESET} %-25s %d Commits geholt\n" "$NAME" "$behind"
|
||||||
|
((pulled++))
|
||||||
|
else
|
||||||
|
printf "${C_RED}FAIL${C_RESET} %-25s Pull fehlgeschlagen (evtl. diverged)\n" "$NAME"
|
||||||
|
((failed++))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
did_something=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Push wenn ahead
|
||||||
|
if ((ahead > 0)); then
|
||||||
|
if $DRY_RUN; then
|
||||||
|
printf "${C_GREEN}PUSH${C_RESET} %-25s %d Commits (dry-run)\n" "$NAME" "$ahead"
|
||||||
|
else
|
||||||
|
if git push --quiet 2>/dev/null; then
|
||||||
|
printf "${C_GREEN}PUSH${C_RESET} %-25s %d Commits gepusht\n" "$NAME" "$ahead"
|
||||||
|
((pushed++))
|
||||||
|
else
|
||||||
|
printf "${C_RED}FAIL${C_RESET} %-25s Push fehlgeschlagen\n" "$NAME"
|
||||||
|
((failed++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
did_something=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! $did_something; then
|
||||||
|
if $has_changes; then
|
||||||
|
printf "${C_YELLOW}DIRTY${C_RESET} %-25s uncommittete Aenderungen\n" "$NAME"
|
||||||
|
((dirty++))
|
||||||
|
else
|
||||||
|
printf "${C_GREEN}OK${C_RESET} %-25s aktuell\n" "$NAME"
|
||||||
|
((uptodate++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- Zusammenfassung -------------------------------------------------------
|
||||||
|
echo
|
||||||
|
echo "${C_BOLD}Gesamt:${C_RESET} $total Repositories"
|
||||||
|
((cloned > 0)) && echo "${C_CYAN}Geklont:${C_RESET} $cloned"
|
||||||
|
((pulled > 0)) && echo "${C_GREEN}Gepullt:${C_RESET} $pulled"
|
||||||
|
((pushed > 0)) && echo "${C_GREEN}Gepusht:${C_RESET} $pushed"
|
||||||
|
((dirty > 0)) && echo "${C_YELLOW}Dirty:${C_RESET} $dirty"
|
||||||
|
((failed > 0)) && echo "${C_RED}Fehlgeschlagen:${C_RESET} $failed"
|
||||||
|
((uptodate > 0)) && echo "${C_GREEN}Aktuell:${C_RESET} $uptodate"
|
||||||
|
echo
|
||||||
Loading…
Add table
Add a link
Reference in a new issue