Files

60 lines
4.6 KiB
Bash
Executable File

#!/bin/bash
# ============================================================================
# 사이트 소스 버전 브랜치(sites/<ID>/...)를 옛 원격 저장소에서 새 저장소로 옮긴다 (v1.4.14, 요구 8)
#
# 1) 옛 원격의 refs/heads/sites/* 를 모두 받아 새 원격에 그대로 올린다 (빠른 진행만 — 새 저장소에 이미 더 새 이력이 있으면 덮지 않음)
# 2) 이 서버의 사이트별 로컬 저장소(data/git/<ID>)는 서비스가 실제로 쓰는 최신 상태이므로, 그 main 과 변경 브랜치를 새 원격에 올리고
# (main 은 강제 — 이 서버의 작업 폴더가 기준) origin 주소를 새 원격으로 바꾼다
# 3) 옛 원격과 새 원격의 브랜치 목록을 비교해 빠진 것이 있으면 알린다
# 옛 원격의 브랜치는 지우지 않는다(확인 뒤 운영자가 정리). 다시 실행해도 안전하다.
#
# 사용: scripts/migrate-gitstore.sh <옛 원격> <새 원격> [--prefix sites] [--data-root ./data]
# 예: scripts/migrate-gitstore.sh git@source-webhosting:OZ-Group/WebHosting_AI_agent.git git@webmaker-gitea:webmaker/sites.git
# ============================================================================
set -euo pipefail
OLD=${1:?옛 원격 git 주소}; NEW=${2:?새 원격 git 주소}; shift 2
PREFIX=sites; DATA_ROOT=$(cd "$(dirname "$0")/.." && pwd)/data
while [ $# -gt 0 ]; do case "$1" in --prefix) PREFIX=$2; shift 2;; --data-root) DATA_ROOT=$2; shift 2;; *) echo "알 수 없는 옵션: $1"; exit 1;; esac; done
export GIT_SSH_COMMAND='ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=15'
export GIT_TERMINAL_PROMPT=0
TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT
echo "== 1/3 옛 원격 $OLD 의 $PREFIX/* 브랜치 받기"
git init -q --bare "$TMP/mirror"
git -C "$TMP/mirror" fetch -q "$OLD" "+refs/heads/$PREFIX/*:refs/heads/$PREFIX/*" 2>&1 | grep -v '^From ' || true
N=$(git -C "$TMP/mirror" for-each-ref --format='%(refname)' "refs/heads/$PREFIX/" | wc -l)
echo " 브랜치 $N 개"
if [ "$N" -gt 0 ]; then
echo "== 2/3 새 원격 $NEW 에 올리기 (빠른 진행만)"
# 한 번에 너무 많으면 ssh 명령줄이 길어지므로 40개씩 묶어 올린다
git -C "$TMP/mirror" for-each-ref --format='%(refname)' "refs/heads/$PREFIX/" > "$TMP/refs.txt"
split -l 40 "$TMP/refs.txt" "$TMP/chunk."
for c in "$TMP"/chunk.*; do
specs=(); while read -r r; do [ -n "$r" ] && specs+=("$r:$r"); done < "$c"
git -C "$TMP/mirror" push -q "$NEW" "${specs[@]}" 2>&1 | grep -vE '^To |^ \* |^$|^remote:' || true
done
fi
# 이 서버의 로컬 사이트 저장소: 최신 상태를 새 원격에 (main 강제), origin 을 새 원격으로
# 다른 서버에서 복사해 온 저장소는 core.worktree 가 그 서버 경로(/var/www/sites/…)라 git 이 "Invalid path" 로 멈춘다 →
# 여기서는 작업 트리가 필요 없으므로 임시 빈 폴더를 GIT_WORK_TREE 로 준다 (서비스는 사용 때마다 alignRepo 로 바로잡는다)
if [ -d "$DATA_ROOT/git" ]; then
echo "== 2b 로컬 사이트 저장소 $DATA_ROOT/git/* → $NEW (origin 변경)"
mkdir -p "$TMP/wt"; export GIT_WORK_TREE="$TMP/wt"
for g in "$DATA_ROOT"/git/*/; do
id=$(basename "$g"); [ -f "$g/HEAD" ] || continue
git --git-dir="$g" remote set-url origin "$NEW" 2>/dev/null || git --git-dir="$g" remote add origin "$NEW" 2>/dev/null || { echo " $id: origin 설정 실패"; continue; }
if git --git-dir="$g" rev-parse -q --verify main >/dev/null 2>&1; then
refs="+refs/heads/main:refs/heads/$PREFIX/$id/main"
for b in $(git --git-dir="$g" for-each-ref --format='%(refname:short)' "refs/heads/$PREFIX/$id/changes/"); do refs="$refs $b:refs/heads/$b"; done
if git --git-dir="$g" push -q origin $refs 2>/dev/null; then echo " $id: main + 변경 브랜치 올림"; else echo " $id: 일부 푸시 실패 (옛 저장소와 다른 커밋의 변경 브랜치 — 서비스가 다음 변경 때 다시 시도)"; fi
fi
done
unset GIT_WORK_TREE
fi
echo "== 3/3 확인"
git ls-remote --heads "$OLD" "refs/heads/$PREFIX/*" 2>/dev/null | awk '{print $2}' | sort > "$TMP/old.txt" || true
git ls-remote --heads "$NEW" "refs/heads/$PREFIX/*" 2>/dev/null | awk '{print $2}' | sort > "$TMP/new.txt" || true
MISSING=$(comm -23 "$TMP/old.txt" "$TMP/new.txt" | wc -l)
echo " 옛 원격 $(wc -l < "$TMP/old.txt")개 · 새 원격 $(wc -l < "$TMP/new.txt")개 · 새 원격에 없는 옛 브랜치 $MISSING 개"
[ "$MISSING" = 0 ] || comm -23 "$TMP/old.txt" "$TMP/new.txt" | sed 's/^/ 없음: /'
echo " 옛 원격의 브랜치는 그대로 두었습니다. 새 원격을 확인한 뒤 지우려면: git push $OLD --delete <브랜치…>"