本文目录导读:

我来介绍几种脚本迁移Git仓库的方法,从简单到复杂。
使用Git原生命令(最基础)
#!/bin/bash # 迁移Git仓库到新地址 # 源仓库地址 OLD_REPO="git@old-server:project.git" # 新仓库地址 NEW_REPO="git@new-server:project.git" # 克隆裸仓库(包含所有分支和标签) git clone --bare $OLD_REPO cd project.git # 添加新远程并推送所有内容 git remote add new-origin $NEW_REPO # 推送所有分支和标签 git push --all new-origin git push --tags new-origin cd .. rm -rf project.git
完整迁移脚本(推荐)
#!/bin/bash
# Git仓库迁移脚本
# 用法: ./git-migrate.sh old-repo-url new-repo-url
set -e
OLD_REPO="$1"
NEW_REPO="$2"
if [ -z "$OLD_REPO" ] || [ -z "$NEW_REPO" ]; then
echo "用法: $0 <旧仓库URL> <新仓库URL>"
exit 1
fi
# 获取仓库名
REPO_NAME=$(basename "$OLD_REPO" .git)
echo "正在迁移仓库: $REPO_NAME"
echo "源地址: $OLD_REPO"
echo "目标地址: $NEW_REPO"
# 步骤1: 克隆裸仓库
echo "步骤1: 克隆源仓库..."
git clone --bare $OLD_REPO
cd "$REPO_NAME.git"
# 步骤2: 显示仓库信息
echo "步骤2: 仓库信息:"
echo " - 分支列表:"
git branch
echo " - 标签列表:"
git tag
echo " - 最后提交:"
git log -1 --format="%H %s"
# 步骤3: 添加新远程
echo "步骤3: 设置新远程仓库..."
git remote add new-origin $NEW_REPO
# 步骤4: 推送所有内容
echo "步骤4: 推送所有分支和标签..."
git push --all new-origin
git push --tags new-origin
# 步骤5: 清理
cd ..
echo "步骤5: 清理临时文件..."
rm -rf "$REPO_NAME.git"
echo "迁移完成!"
Python脚本(更灵活)
#!/usr/bin/env python3
# git_migrate.py
import os
import sys
import shutil
import subprocess
import json
from pathlib import Path
class GitMigrator:
def __init__(self, old_url, new_url):
self.old_url = old_url
self.new_url = new_url
self.repo_name = self._get_repo_name()
self.temp_dir = Path.cwd() / f"{self.repo_name}_temp"
def _get_repo_name(self):
"""从URL提取仓库名"""
name = self.old_url.rstrip('/').split('/')[-1]
return name.replace('.git', '')
def _run_command(self, cmd, cwd=None):
"""运行命令并返回输出"""
result = subprocess.run(
cmd,
shell=True,
cwd=cwd or str(self.temp_dir),
capture_output=True,
text=True
)
if result.returncode != 0:
print(f"命令失败: {cmd}")
print(f"错误: {result.stderr}")
sys.exit(1)
return result.stdout.strip()
def get_repo_info(self):
"""获取仓库信息"""
os.chdir(str(self.temp_dir))
info = {
"branches": [],
"tags": [],
"last_commit": ""
}
try:
# 获取分支列表
branches = self._run_command("git branch -r")
info["branches"] = [b.strip() for b in branches.split('\n') if b.strip()]
# 获取标签列表
tags = self._run_command("git tag")
info["tags"] = [t.strip() for t in tags.split('\n') if t.strip()]
# 获取最后提交
info["last_commit"] = self._run_command("git log -1 --format='%H %s'")
except:
pass
return info
def migrate(self):
"""执行迁移"""
print(f"开始迁移仓库: {self.repo_name}")
print(f"源: {self.old_url}")
print(f"目标: {self.new_url}")
try:
# 步骤1: 克隆裸仓库
print("\n[1/4] 克隆源仓库...")
cmd = f"git clone --bare {self.old_url} {self.temp_dir.name}"
self._run_command(cmd, cwd=Path.cwd())
# 步骤2: 获取仓库信息
print("\n[2/4] 获取仓库信息...")
info = self.get_repo_info()
print(f" 分支数量: {len(info['branches'])}")
print(f" 标签数量: {len(info['tags'])}")
print(f" 最后提交: {info['last_commit']}")
# 步骤3: 设置新远程并推送
print("\n[3/4] 推送至新仓库...")
self._run_command(f"git remote add new-origin {self.new_url}")
self._run_command("git push --all new-origin")
self._run_command("git push --tags new-origin")
print("\n[4/4] 清理临时文件...")
os.chdir(str(Path.cwd()))
shutil.rmtree(str(self.temp_dir))
print(f"\n✅ 迁移成功!")
return True
except Exception as e:
print(f"\n❌ 迁移失败: {e}")
# 清理
if self.temp_dir.exists():
shutil.rmtree(str(self.temp_dir))
return False
def main():
if len(sys.argv) != 3:
print("用法: python git_migrate.py <旧仓库URL> <新仓库URL>")
print("示例: python git_migrate.py git@old.com:project.git git@new.com:project.git")
sys.exit(1)
migrator = GitMigrator(sys.argv[1], sys.argv[2])
migrator.migrate()
if __name__ == "__main__":
main()
批量迁移脚本
#!/bin/bash
# batch-git-migrate.sh - 批量迁移多个Git仓库
# 配置文件:每行格式 "旧URL 新URL"
CONFIG_FILE="repos.txt"
# 迁移列表文件示例内容:
# git@old-server:project1.git git@new-server:project1.git
# git@old-server:project2.git git@new-server:project2.git
# git@old-server:project3.git git@new-server:project3.git
log_file="migration_$(date +%Y%m%d_%H%M%S).log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$log_file"
}
migrate_repo() {
local old_url="$1"
local new_url="$2"
local repo_name=$(basename "$old_url" .git)
log "开始迁移: $repo_name"
# 克隆裸仓库
if ! git clone --bare "$old_url" "/tmp/$repo_name.git" 2>> "$log_file"; then
log " ❌ 克隆失败: $repo_name"
return 1
fi
cd "/tmp/$repo_name.git"
# 添加新远程并推送
if ! git remote add new-origin "$new_url" 2>> "$log_file"; then
log " ❌ 添加远程失败: $repo_name"
cd /
rm -rf "/tmp/$repo_name.git"
return 1
fi
# 推送所有内容
if ! git push --all new-origin 2>> "$log_file" || ! git push --tags new-origin 2>> "$log_file"; then
log " ❌ 推送失败: $repo_name"
cd /
rm -rf "/tmp/$repo_name.git"
return 1
fi
cd /
rm -rf "/tmp/$repo_name.git"
log " ✅ 迁移成功: $repo_name"
return 0
}
# 主流程
log "开始批量迁移Git仓库..."
log "配置文件: $CONFIG_FILE"
if [ ! -f "$CONFIG_FILE" ]; then
log "❌ 配置文件不存在: $CONFIG_FILE"
exit 1
fi
success=0
failed=0
total=0
while IFS=' ' read -r old_url new_url || [ -n "$old_url" ]; do
# 跳过空行和注释
[[ -z "$old_url" || "$old_url" =~ ^# ]] && continue
total=$((total + 1))
if migrate_repo "$old_url" "$new_url"; then
success=$((success + 1))
else
failed=$((failed + 1))
fi
done < "$CONFIG_FILE"
log "迁移完成!"
log "总计: $total, 成功: $success, 失败: $failed"
# 显示报告
echo ""
echo "========== 迁移报告 =========="
echo "总计仓库数: $total"
echo "成功迁移: $success"
echo "失败: $failed"
echo "日志文件: $log_file"
echo "=============================="
带进度显示的脚本
#!/bin/bash
# git-migrate-progress.sh
source_repo="$1"
target_repo="$2"
show_progress() {
local current=$1
local total=$2
local width=50
local percentage=$((current * 100 / total))
local completed=$((width * current / total))
printf "\r进度: ["
for ((i=0; i<completed; i++)); do printf "#"; done
for ((i=completed; i<width; i++)); do printf " "; done
printf "] %d%%" $percentage
}
echo "===== Git仓库迁移工具 ====="
echo "源: $source_repo"
echo "目标: $target_repo"
echo ""
# 设置陷阱,确保清理
trap 'echo ""; echo "迁移中断,清理中..."; rm -rf /tmp/*.git 2>/dev/null; exit 1' INT TERM
# 步骤1: 克隆
echo "步骤1/3: 克隆源仓库..."
show_progress 1 3
git clone --bare "$source_repo" /tmp/migrate_temp.git 2>/dev/null
if [ $? -ne 0 ]; then
echo ""
echo "❌ 克隆失败"
exit 1
fi
cd /tmp/migrate_temp.git || exit 1
# 步骤2: 添加远程
echo ""
echo "步骤2/3: 配置目标仓库..."
show_progress 2 3
git remote add new-origin "$target_repo" 2>/dev/null
# 步骤3: 推送
echo ""
echo "步骤3/3: 推送数据..."
show_progress 3 3
git push --all new-origin 2>/dev/null
git push --tags new-origin 2>/dev/null
# 清理
cd /
rm -rf /tmp/migrate_temp.git
echo ""
echo ""
echo "✅ 迁移完成!"
使用建议
- 权限检查:确保有源仓库的读取权限和目标仓库的写入权限
- 网络测试:大仓库迁移前先测试网络连接
- 增量迁移:对于大型仓库,考虑分批迁移
- 验证:迁移后在新仓库验证所有分支和标签
- 备份:重要仓库迁移前先在源端创建备份
执行示例:
# 基本迁移 chmod +x git-migrate.sh ./git-migrate.sh git@old-server:project.git git@new-server:project.git # Python版本 python3 git_migrate.py git@old-server:project.git git@new-server:project.git # 批量迁移 ./batch-git-migrate.sh
选择哪种脚本取决于你的具体需求,推荐使用第2个完整性较高的Shell脚本。