#!/bin/bash set -euo pipefail BRANCH=$(hostname) ANGIE_CONF_DIR="/etc/angie/http.d/" PTAF_CONF_DIR="/home/install/conf/ptaf-nginx/" REPO_URL="https://{{ git_token }}@svc-git.cirex.ru/cloudstack/ptaf_config_logs.git" # Функция для обработки одной директории process_directory() { local dir="$1" local branch_suffix="$2" local full_branch="${BRANCH}-${branch_suffix}" echo "$(date '+%Y-%m-%d %H:%M:%S') ======================================" echo "$(date '+%Y-%m-%d %H:%M:%S') Processing directory: $dir" echo "$(date '+%Y-%m-%d %H:%M:%S') Branch: $full_branch" cd "$dir" # Если это не git-репозиторий — инициализируем новый if [ ! -d ".git" ]; then echo "$(date '+%Y-%m-%d %H:%M:%S') Инициализируем новый локальный git-репозиторий" git init git config user.name "ptaf-sync-script" git config user.email "ptaf-sync-script@$(hostname)" fi # Настраиваем пользователя git config user.name "ptaf-sync-script" 2>/dev/null || true git config user.email "ptaf-sync-script@$(hostname)" 2>/dev/null || true # Настраиваем стратегию разрешения конфликтов: всегда предпочитать локальную версию git config pull.rebase true git config rebase.autoStash true # Добавляем/проверяем remote origin if ! git remote | grep -q '^origin$'; then echo "$(date '+%Y-%m-%d %H:%M:%S') Добавляем remote origin" git remote add origin "$REPO_URL" else git remote set-url origin "$REPO_URL" fi # Очищаем возможные битые ссылки echo "$(date '+%Y-%m-%d %H:%M:%S') Очищаем старые ссылки" git remote prune origin 2>/dev/null || true # КЛЮЧЕВОЕ ИЗМЕНЕНИЕ: Получаем только нашу ветку echo "$(date '+%Y-%m-%d %H:%M:%S') Проверяем существование ветки '$full_branch' на сервере" if git ls-remote --heads origin "$full_branch" | grep -q "$full_branch"; then echo "$(date '+%Y-%m-%d %H:%M:%S') Ветка существует на сервере, получаем её" git fetch origin "$full_branch:refs/remotes/origin/$full_branch" --force 2>/dev/null || { echo "$(date '+%Y-%m-%d %H:%M:%S') Ошибка при fetch, очищаем и повторяем" rm -f .git/refs/remotes/origin/"$full_branch" git fetch origin "$full_branch:refs/remotes/origin/$full_branch" --force 2>/dev/null || true } BRANCH_EXISTS_REMOTE=true else echo "$(date '+%Y-%m-%d %H:%M:%S') Ветка '$full_branch' ещё не существует на сервере" BRANCH_EXISTS_REMOTE=false fi # Проверяем, существует ли ветка локально if ! git show-ref --verify --quiet refs/heads/"$full_branch"; then echo "$(date '+%Y-%m-%d %H:%M:%S') Создаём локальную ветку '$full_branch'" if [ "$BRANCH_EXISTS_REMOTE" = true ]; then # Создаём ветку на основе удалённой git checkout -b "$full_branch" "origin/$full_branch" else # Создаём новую orphan ветку git checkout --orphan "$full_branch" 2>/dev/null || git checkout -b "$full_branch" git rm -rf . 2>/dev/null || true fi else git checkout "$full_branch" 2>/dev/null || { echo "$(date '+%Y-%m-%d %H:%M:%S') Ошибка переключения, принудительно переключаемся" git checkout -f "$full_branch" } fi # Добавляем все файлы echo "$(date '+%Y-%m-%d %H:%M:%S') Добавляем все файлы" git add -A . # Проверяем наличие изменений и коммитим ИХ СНАЧАЛА if ! git diff-index --quiet HEAD -- 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then COMMIT_MSG="Config update $(date '+%Y-%m-%d %H:%M:%S') [host: $(hostname -s)]" echo "$(date '+%Y-%m-%d %H:%M:%S') Обнаружены локальные изменения — коммитим их ПЕРЕД pull" git commit -m "$COMMIT_MSG" fi # Теперь делаем pull/rebase если ветка существует на сервере if [ "$BRANCH_EXISTS_REMOTE" = true ]; then echo "$(date '+%Y-%m-%d %H:%M:%S') Синхронизация с удалённой веткой origin/$full_branch" # Вариант 1: Пробуем обычный rebase if git pull --rebase origin "$full_branch" 2>/dev/null; then echo "$(date '+%Y-%m-%d %H:%M:%S') Rebase успешен" else echo "$(date '+%Y-%m-%d %H:%M:%S') Конфликт при rebase, разрешаем автоматически" # Прерываем rebase git rebase --abort 2>/dev/null || true # Вариант 2: Используем стратегию merge с предпочтением локальных изменений echo "$(date '+%Y-%m-%d %H:%M:%S') Используем merge стратегию с предпочтением локальных изменений" if git pull --no-rebase --strategy=recursive --strategy-option=ours origin "$full_branch" 2>/dev/null; then echo "$(date '+%Y-%m-%d %H:%M:%S') Merge успешен с предпочтением локальных изменений" else echo "$(date '+%Y-%m-%d %H:%M:%S') Merge также не удался, используем force push" # Вариант 3: Если и merge не сработал - будем пушить с force # (это безопасно, так как мы уже закоммитили все локальные изменения) fi fi fi # Создаём keepalive коммит, если изменений больше нет if git diff-index --quiet HEAD -- 2>/dev/null && git diff --cached --quiet 2>/dev/null; then COMMIT_MSG="No changes – keepalive commit $(date '+%Y-%m-%d %H:%M:%S') [host: $(hostname -s)]" echo "$(date '+%Y-%m-%d %H:%M:%S') Нет новых изменений — создаём пустой коммит" git commit --allow-empty -m "$COMMIT_MSG" fi # Пушим с fallback вариантами echo "$(date '+%Y-%m-%d %H:%M:%S') Пушим ветку $full_branch" if git push origin "$full_branch" --set-upstream 2>/dev/null; then echo "$(date '+%Y-%m-%d %H:%M:%S') Push успешен" elif git push origin "$full_branch" --force-with-lease 2>/dev/null; then echo "$(date '+%Y-%m-%d %H:%M:%S') Push успешен с --force-with-lease" else echo "$(date '+%Y-%m-%d %H:%M:%S') Используем force push (локальные изменения приоритетнее)" git push origin "$full_branch" --force || { echo "$(date '+%Y-%m-%d %H:%M:%S') ОШИБКА: Не удалось запушить ветку $full_branch" return 1 } fi echo "$(date '+%Y-%m-%d %H:%M:%S') Успешно завершено: $dir" return 0 } # Обрабатываем первую директорию if [ -d "$ANGIE_CONF_DIR" ]; then process_directory "$ANGIE_CONF_DIR" "angie-conf" || { echo "$(date '+%Y-%m-%d %H:%M:%S') ОШИБКА при обработке $ANGIE_CONF_DIR" } else echo "$(date '+%Y-%m-%d %H:%M:%S') ПРЕДУПРЕЖДЕНИЕ: Директория $ANGIE_CONF_DIR не найдена" fi # Обрабатываем вторую директорию if [ -d "$PTAF_CONF_DIR" ]; then process_directory "$PTAF_CONF_DIR" "ptaf-conf" || { echo "$(date '+%Y-%m-%d %H:%M:%S') ОШИБКА при обработке $PTAF_CONF_DIR" } else echo "$(date '+%Y-%m-%d %H:%M:%S') ПРЕДУПРЕЖДЕНИЕ: Директория $PTAF_CONF_DIR не найдена" fi echo "$(date '+%Y-%m-%d %H:%M:%S') ======================================" echo "$(date '+%Y-%m-%d %H:%M:%S') All backups completed."