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
└── refs

5 directories, 4 files


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

python示例代码

import os
import sys
import time

class GitMirror():
    def __init__(self):
        pass

    @staticmethod
    def os_system(cmd):
        print("execute command [%s]" % cmd)
        os.system(cmd)

    @staticmethod
    def mirror_fetch(local_path, remote_path):
        local_git_path = local_path + ".git"
        parent_path = os.path.dirname(local_git_path)
        # not first run
        if 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 clone
            print("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 requests

class GitlabApi():

    def __init__(self, token, url):
        self.token = token
        self.url = "%s%s" %(url, "api/v4/")
        self.header = {
            "Content-Type": "application/json",
            "Private-Token": self.token
            }

    def get_all_projects(self):
        data = []
        page = 0
        total_pages = 1
        while 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 += 1
        return data


if __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 requests


class GitlabApi():

    def __init__(self, token, url):
        self.token = token
        self.url = "%s%s" %(url, "api/v4/")
        self.header = {
            "Content-Type": "application/json",
            "Private-Token": self.token
            }

    def get_all_projects(self):
        data = []
        page = 0
        total_pages = 1
        while 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 += 1
        return data


class GitMirror():
    def __init__(self):
        pass

    @staticmethod
    def os_system(cmd):
        print("execute command [%s]" % cmd)
        os.system(cmd)

    @staticmethod
    def mirror_fetch(local_path, remote_path):
        local_git_path = local_path + ".git"
        parent_path = os.path.dirname(local_git_path)
        # not first run
        if 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 clone
            print("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))
  • 18
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现批量进行git clone操作,你可以按照以下步骤操作: 1. 首先,创建一个名为batch_git_clone.sh的shell脚本文件,并将下面的代码复制到文件中: ``` #!/bin/sh echo "批量git clone开始!" while read git_url do # 过滤空行,以及#开头的注释行 [[ -z $git_url || $git_url =~ ^#.* ]] && continue git clone ${git_url} done < $1 wait echo "批量git clone结束!" ``` 这个脚本会读取存放git url的文件,并逐行进行git clone操作。 2. 接下来,创建一个名为git_url_list.txt的文本文件,并将需要进行git clone仓库的url按行存放在该文件中,例如: ``` https://github.com/xxx/xxx.git https://github.com/xxx/xxx.git ``` 3. 运行batch_git_clone.sh脚本,将git_url_list.txt文件作为参数传递给脚本,即: ``` ./batch_git_clone.sh git_url_list.txt ``` 执行上述命令后,脚本会逐行读取git_url_list.txt文件中的url,并进行git clone操作。 这样,你就可以批量进行git clone操作了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [批量 git clone](https://blog.csdn.net/myzryo/article/details/129495923)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [git批量克隆 批量切换分支 批量pull](https://blog.csdn.net/weixin_41130251/article/details/127997092)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值