因业务限制,需要在两个代码仓库进行周期性的同步代码。大概逻辑是使用git clone --mirror方式将源仓库中的代码clone到本地主机上,然后推送到目标仓库中。

以下代码实现了如下逻辑

参数为配置文件,逐行读取配置文件,拉取代码到临时目录,并根据源仓库替换字符串生成目标残酷地址,并将代码推送到目标仓库。完成操作后,清除所有临时文件。

#!/bin/bash

# Git 仓库批量镜像迁移脚本(修复日志记录问题)
# 输入文件格式:旧仓库地址(SSH)(单列)

# 检查输入参数
if [ $# -ne 1 ]; then
    echo "用法: $0 <仓库列表文件.txt>"
    echo "文件格式示例:"
    echo "git@codehub.devcloud.ap-southeast-3.huaweicloud.com:18b23414ec9e475a8b56861b69afca68/repo1.git"
    exit 1
fi

REPO_LIST_FILE=$1
TMP_DIR="/tmp/git_mirror_migration_$(date +%s)"
LOG_FILE="git_migration_$(date +%Y%m%d_%H%M%S).log"
# 两个仓库结构相同,只是ID不同,只要简单替换即可
OLD_ID="aaaaaaaaa"
NEW_ID="bbbbbbbbb"

# 创建临时目录
mkdir -p "$TMP_DIR"

# 初始化日志文件(使用exec保持文件描述符打开)
exec 3>&1 4>&2
exec > >(tee -a "$LOG_FILE") 2>&1

echo "Git 仓库镜像迁移日志 - $(date)"
echo "临时目录: $TMP_DIR"
echo "正在将仓库地址中的 $OLD_ID 替换为 $NEW_ID"
echo "======================================"

# 处理单列文件
while read -r SOURCE_REPO; do
    # 跳过空行和注释行(以#开头的行)
    [[ -z "$SOURCE_REPO" || "$SOURCE_REPO" =~ ^# ]] && continue

    # 生成目标仓库地址
    TARGET_REPO="${SOURCE_REPO//$OLD_ID/$NEW_ID}"
    REPO_NAME=$(basename "$SOURCE_REPO" .git)

    echo
    echo "正在处理仓库: $REPO_NAME"
    echo "源地址: $SOURCE_REPO"
    echo "目标地址: $TARGET_REPO"

    # 进入临时目录
    cd "$TMP_DIR" || exit 1

    # 1. 镜像克隆源仓库
    echo "[1/3] 正在镜像克隆..."
    if ! git clone --mirror "$SOURCE_REPO" "$REPO_NAME" 2>&1; then
        echo "错误: 克隆仓库失败!"
        continue
    fi

    # 2. 进入仓库目录
    cd "$REPO_NAME" || continue

    # 3. 推送到目标仓库
    echo "[2/3] 正在镜像推送..."
    if git push --mirror "$TARGET_REPO" 2>&1; then
        echo "[3/3] 成功: 仓库迁移完成!"
    else
        echo "错误: 推送仓库失败!"
    fi

    # 4. 返回临时目录并清理
    cd "$TMP_DIR" && rm -rf "$REPO_NAME"

done < "$REPO_LIST_FILE"

# 恢复标准输出
exec 1>&3 2>&4

echo
echo "迁移完成,清理临时目录..."
rm -rf "$TMP_DIR"

echo "======================================"
echo "所有操作已完成,详细日志请查看: $LOG_FILE"

# 将结束信息也写入日志
exec 3>&1 4>&2
exec > >(tee -a "$LOG_FILE") 2>&1
echo "脚本执行结束时间: $(date)"
exec 1>&3 2>&4
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.

以上代码一直正常使用,直到今天,突然报错,

使用git push --mirror出现pre-receive hook declined问题解决方法_合并

提示 The keywords cherry-pick and revert are branch names reserved by CodeHub, You are not allowed to create.并且所有的分支都被拒绝 (pre-receive hook declined)

手动clone代码并重新设定remote

git clone --mirror aaaaa

git reote add repo bbbbb

查看所有分支

git branch -a

可以看到tmp开头的分支,此分支为代码合并期间的临时分支。

使用git push --mirror出现pre-receive hook declined问题解决方法_合并_02

查看源仓库,发现有为完成的合并请求。

在本地删除此分支

git branch -D tmp-branch-xxxx

重新push

git push repo +refs/heads/*:refs/heads/*

问题解决