当前位置: 首页 > news >正文

git仓库批量备份

git的mirror参数

在git中,--mirror是一个用于克隆和推送操作的参数。它用于创建一个镜像仓库,包含了源仓库的所有分支、标签和提交历史记录。

当使用git clone --mirror <source-repo>命令时,会创建一个完全相同的镜像仓库,其中包含源仓库的所有内容。与普通克隆不同,镜像仓库会将所有的分支和标签都设为跟踪远程仓库的分支和标签。这意味着可以使用镜像仓库进行完整的版本控制操作,包括查看历史记录、切换分支等。

对于已经clone下载的仓库,如果远程仓库更新了,则可以用git fetch --prune对本地仓库保持同步。当执行该命令时,git会从远程仓库获取最新的提交和分支信息,并将这些更新同步到本地仓库的远程跟踪分支中。同时,它还会检查本地的远程跟踪分支,如果在远程仓库中已经删除了某个分支,那么它也会将这个本地的远程跟踪分支删除。

当在镜像仓库上执行git push --mirror <destination-repo>命令时,将会把镜像仓库的所有内容推送到目标仓库中,包括分支、标签和提交历史记录。

利用这些特性我们就可以完整备份git仓库。

命令行操作

$ git clone --mirror git@git.example.com/example.git
Cloning into bare repository 'example.git'...
remote: Enumerating objects: 760, done.
remote: Counting objects: 100% (760/760), done.
remote: Compressing objects: 100% (438/438), done.
remote: Total 760 (delta 280), reused 759 (delta 279)
Receiving objects: 100% (760/760), 4.79 MiB | 9.97 MiB/s, done.
Resolving deltas: 100% (280/280), done.
$ cd example.git/
$ tree -L 1
.
├── branches
├── config
├── description
├── HEAD
├── hooks
├── info
├── objects
├── packed-refs
└── refs5 directories, 4 files

需要使用ssh或者git地址,不要使用http地址,并把ssh public key传输到git服务器上,避免clone的时候需要输入密码。对于单个仓库,手动执行足够了,但对于批量仓库操作需要封装成api待用。

python示例代码

import os
import sys
import timeclass GitMirror():def __init__(self):pass@staticmethoddef os_system(cmd):print("execute command [%s]" % cmd)os.system(cmd)@staticmethoddef mirror_fetch(local_path, remote_path):local_git_path = local_path + ".git"parent_path = os.path.dirname(local_git_path)# not first runif os.path.exists(local_git_path):print("enter [%s] and fetch" % (local_git_path))GitMirror.os_system("git --git-dir=%s fetch --prune" % local_git_path)else:  # first run, git cloneprint("git clone mirror from [%s] " % (remote_path))GitMirror.os_system("mkdir -p %s; cd %s; git clone --mirror %s" % (parent_path, parent_path, remote_path))time.sleep(0.2)if __name__ == "__main__":GitMirror.mirror_fetch("/home/dev/backup/example", "git@git.example.com/example.git")

批量获取仓库地址

gitlab, github, gitee,gerrit等git托管服务都提供了REST api,可以通过这些api批量获取仓库信息。以gitlab为例(https://docs.gitlab.com/ee/api/rest/ )

一 获取Access Tokens

首先需要获取Acess Tokens, 在gitlab用户管理界面中找到 “Access Tokens” 标签,输入token名字,勾选 "api"生成token。注意,生成token后务必保存下来,因为后面就再也看不到了,如果没存下来,只能重新生成。
在这里插入图片描述

二 通过api获取全部projects

通过curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects"可以获取本人以及本人可见的项目(Projects API | GitLab)。

把curl命令转换成python。

在获取全部项目的时候,每次只能返回1页的项目,所以想要获取全部项目,需要分页获取。

返回的项目信息中,有一个非常重要的字段"ssh_url_to_repo",有了项目地址就可以进行完整备份了。

import requestsclass GitlabApi():def __init__(self, token, url):self.token = tokenself.url = "%s%s" %(url, "api/v4/")self.header = {"Content-Type": "application/json","Private-Token": self.token}def get_all_projects(self):data = []page = 0total_pages = 1while page < total_pages:api_url = "%s%s%s" % (self.url, "projects", "?page=%d" % page)res = requests.get(api_url, headers = self.header)total_pages = int(res.headers["X-Total-Pages"])data += res.json()page += 1return dataif __name__ == "__main__":api = GitlabApi("your_token", "http://git.example.com/")res = api.get_all_projects()for i in res:print(i)

三 根据项目信息备份全部仓库

根据服务器的路径,在本地也做一个对应的目录结构。

def signal_handler(signum, frame):sys.exit(0)if __name__ == "__main__":signal.signal(signal.SIGINT, signal_handler)signal.signal(signal.SIGTERM, signal_handler)api = GitlabApi("your_token", "http://git.example.com/")download_path = os.path.join(os.path.abspath(os.getcwd()), "tmp")res = api.get_all_projects()for i in res:path = os.path.join(download_path, i["path_with_namespace"])GitMirror.mirror_fetch(path, i["ssh_url_to_repo"])with open("%s%s.json"%(path, i["name"]), "w") as fout:fout.write(json.dumps(i, indent=4))print("total %d" % len(res))

完整代码

import json
import os.path
import sys
import signal
import time
import requestsclass GitlabApi():def __init__(self, token, url):self.token = tokenself.url = "%s%s" %(url, "api/v4/")self.header = {"Content-Type": "application/json","Private-Token": self.token}def get_all_projects(self):data = []page = 0total_pages = 1while page < total_pages:api_url = "%s%s%s" % (self.url, "projects", "?page=%d" % page)res = requests.get(api_url, headers = self.header)total_pages = int(res.headers["X-Total-Pages"])data += res.json()page += 1return dataclass GitMirror():def __init__(self):pass@staticmethoddef os_system(cmd):print("execute command [%s]" % cmd)os.system(cmd)@staticmethoddef mirror_fetch(local_path, remote_path):local_git_path = local_path + ".git"parent_path = os.path.dirname(local_git_path)# not first runif os.path.exists(local_git_path):print("enter [%s] and fetch" % (local_git_path))GitMirror.os_system("git --git-dir=%s fetch --prune" % local_git_path)else:  # first run, git cloneprint("git clone mirror from [%s] " % (remote_path))GitMirror.os_system("mkdir -p %s; cd %s; git clone --mirror %s" % (parent_path, parent_path, remote_path))time.sleep(0.2)def signal_handler(signum, frame):sys.exit(0)if __name__ == "__main__":signal.signal(signal.SIGINT, signal_handler)signal.signal(signal.SIGTERM, signal_handler)api = GitlabApi("your_token", "http://git.example.com/")download_path = os.path.join(os.path.abspath(os.getcwd()), "tmp")res = api.get_all_projects()for i in res:path = os.path.join(download_path, i["path_with_namespace"])GitMirror.mirror_fetch(path, i["ssh_url_to_repo"])with open("%s%s.json"%(path, i["name"]), "w") as fout:fout.write(json.dumps(i, indent=4))print("total %d" % len(res))

相关文章:

  • LeetCode 54 螺旋矩阵
  • 扩展学习|商业智能和大数据分析的研究前景(比对分析)
  • 【Vue.js设计与实现】第一篇:框架设计概览-阅读笔记(持续更新)
  • 【Linux笔记】文件描述符与重定向
  • 《统计学习方法:李航》笔记 从原理到实现(基于python)-- 第5章 决策树(代码python实践)
  • ingres nginx 反向代理常见配置(持续更新)
  • 盘点Python网页开发轻量级框架Flask知识
  • C++ 数论相关题目 博弈论 Nim游戏
  • 微信小程序(二十五)条件判断语句与结构隐藏
  • Django视图函数技巧,从入门到实战
  • 开源电商系统
  • LeetCode每日一题 | 2808. 使循环数组所有元素相等的最少秒数
  • 搭建幻兽帕鲁需要什么样的服务器
  • 工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计
  • 【蓝桥杯冲冲冲】进阶搜索 Anya and Cubes
  • 【技术性】Search知识
  • CSS 专业技巧
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • JavaWeb(学习笔记二)
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • js ES6 求数组的交集,并集,还有差集
  • JS 面试题总结
  • Spring声明式事务管理之一:五大属性分析
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 利用jquery编写加法运算验证码
  • 设计模式走一遍---观察者模式
  • 阿里云服务器购买完整流程
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ###STL(标准模板库)
  • #QT项目实战(天气预报)
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (1)(1.9) MSP (version 4.2)
  • (145)光线追踪距离场柔和阴影
  • (2)空速传感器
  • (6)设计一个TimeMap
  • (SpringBoot)第七章:SpringBoot日志文件
  • (动态规划)5. 最长回文子串 java解决
  • (七)理解angular中的module和injector,即依赖注入
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (转)德国人的记事本
  • .NET 反射 Reflect
  • .NET6 命令行启动及发布单个Exe文件
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .skip() 和 .only() 的使用
  • @property @synthesize @dynamic 及相关属性作用探究
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • @Transactional事务注解内含乾坤?
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [4]CUDA中的向量计算与并行通信模式
  • [Android]如何调试Native memory crash issue
  • [BZOJ] 3262: 陌上花开
  • [C#] 如何调用Python脚本程序
  • [C#]使用DlibDotNet人脸检测人脸68特征点识别人脸5特征点识别人脸对齐人脸比对FaceMesh
  • [C++]使用yolov10的onnx模型结合onnxruntime和bytetrack实现目标追踪