自动从私有 GitLab 服务器批量拉取(或克隆)项目代码,并同步所有远程分支的最新内容到本地
代码
# ==============================================
# 说明:
# gitLab需要配置成自己的参数
# groupName为空则拉取所有项目,否则拉取group下面的项目
# ==============================================
import tkinter as tk
from tkinter import filedialog
from urllib.request import urlopen
import json
import os
from git.repo import Repo
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
# 配置gitLab
gitlabAddr = "--" # 192.168.1.1:80
gitlabPrivateToken = "--" # 访问令牌
groupName = ""
# 设置本地存储路径
root = tk.Tk()
root.withdraw()
folderPath = r"--" # D:/gitlab
# 构建 API URL
if groupName == "":
url = f"http://{gitlabAddr}/api/v4/projects?private_token={gitlabPrivateToken}&per_page=1000&order_by=name"
else:
# 注意:GitLab v4 API 中 groups 的 projects 接口路径已变更
url = f"http://{gitlabAddr}/api/v4/groups/{groupName}/projects?private_token={gitlabPrivateToken}&per_page=1000&order_by=name"
print("Fetching projects from:", url)
# 获取项目列表
with urlopen(url) as response:
allProjectsDict = json.loads(response.read().decode("UTF-8"))
# 反转顺序(可选)
allProjectsDict.reverse()
# 线程安全的日志打印
print_lock = threading.Lock()
def log(msg):
with print_lock:
print(msg)
def sync_project(thisProject):
try:
thisProjectURL = thisProject["http_url_to_repo"]
thisProjectPath = thisProject["path_with_namespace"]
filePath = os.path.join(folderPath, thisProjectPath)
log(f"Processing: {thisProjectURL} -> {filePath}")
if os.path.exists(filePath):
repo = Repo(filePath)
log(f" -> Pulling existing repo: {filePath}")
else:
os.makedirs(os.path.dirname(filePath), exist_ok=True)
repo = Repo.clone_from(thisProjectURL, filePath)
log(f" -> Cloned new repo: {filePath}")
remote = repo.remote()
remote_branch_names = [
ref for ref in remote.refs if not ref.remote_head.startswith("HEAD")
]
for ref in remote_branch_names:
branch_name = ref.remote_head
try:
repo.git.checkout(branch_name, force=True)
repo.git.pull()
log(f" -> Updated branch: {branch_name}")
except Exception as e:
log(f" !! Error pulling branch {branch_name} in {filePath}: {e}")
except Exception as e:
log(
f"!! Failed to process {thisProject.get('http_url_to_repo', 'unknown')}: {e}"
)
# 并发执行
max_workers = 10 # 可根据网络和磁盘性能调整
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(sync_project, project) for project in allProjectsDict]
for future in as_completed(futures):
# 异常已在 sync_project 内部处理,此处可选是否 re-raise
pass
log("All projects synchronized.")
🎯 这段代码的作用:
自动从 GitLab 下载(或更新)你所有的项目代码到本地电脑。
就像你手动一个个点“克隆”或“拉取更新”一样,但它能一次性自动做完所有项目,还支持多任务同时进行,省时省力。
🔧 你需要改的地方(配置):
- GitLab 地址:比如
192.168.1.1:80 - 你的访问令牌(Private Token):在 GitLab 账号里生成,用来证明你是谁。
- 要不要只下载某个组(groupName)的项目?
- 留空 → 下载你有权限的所有项目
- 填名字 → 只下载这个组里的项目
- 本地保存路径:比如
D:/gitlab,所有代码会存到这里,按原项目结构组织(如公司/部门/项目名)
🔄 它是怎么工作的?
- 先问 GitLab:“我有哪些项目?”(通过 API 获取列表)
- 对每个项目:
- 如果本地没有这个项目 → 就
git clone下来 - 如果本地已经有 → 就
git pull更新最新代码
- 如果本地没有这个项目 → 就
- 还会把每个项目的每个分支都更新一遍(这点可能有点多,一般只需要主分支)
- 多个项目可以同时下载/更新(最多10个一起跑),更快!
✅ 举个例子:
假设你在 GitLab 有这些项目:
mygroup/backendmygroup/frontend
运行脚本后,它会在你电脑上自动创建:
D:/gitlab/mygroup/backend/
D:/gitlab/mygroup/frontend/
并且确保它们都是最新代码。
⚠️ 注意:
- 你需要提前安装 Python 和几个库(比如
gitpython) - 如果项目特别多(超过1000个),可能需要改代码支持分页
- 群组名字如果带斜杠(比如
parent/group),可能要特殊处理
💡 总结一句话:
这是一个“一键同步 GitLab 所有项目到本地”的自动化小工具。
8788

被折叠的 条评论
为什么被折叠?



