本文目录导读:

我来介绍几种脚本迁移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脚本。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播