如何在 GitLab 中一次克隆一个组的所有项目?
How to clone all projects of a group at once in GitLab?
在我的 GitLab 存储库中,我有一个包含 20 个项目的组。我想一次克隆所有项目。这可能吗?
不是真的,除非:
你有一个第 21 个项目引用了其他 20 个项目 submodules。
(在这种情况下,一个克隆后跟一个 git submodule update --init
就足以克隆并签出所有 20 个项目)
或者您以某种方式列出您有权访问的项目 (GitLab API for projects),然后循环该结果以克隆每个项目(这意味着可以编写脚本,然后作为“一个”执行命令)
自 2015 年以来,Jay Gabez mentions (August 2019) the tool gabrie30/ghorg
ghorg
allows you to quickly clone all of an org's or user's repos into a single directory.
用法:
$ ghorg clone someorg
$ ghorg clone someuser --clone-type=user --protocol=ssh --branch=develop
$ ghorg clone gitlab-org --scm=gitlab --namespace=gitlab-org/security-products
$ ghorg clone --help
另外 (2020):https://github.com/ezbz/gitlabber
usage: gitlabber [-h] [-t token] [-u url] [--debug] [-p]
[--print-format {json,yaml,tree}] [-i csv] [-x csv]
[--version]
[dest]
Gitlabber - clones or pulls entire groups/projects tree from gitlab
这是 Python 3 中的示例:
from urllib.request import urlopen
import json
import subprocess, shlex
allProjects = urlopen("https://[yourServer:port]/api/v4/projects?private_token=[yourPrivateTokenFromUserProfile]&per_page=100000")
allProjectsDict = json.loads(allProjects.read().decode())
for thisProject in allProjectsDict:
try:
thisProjectURL = thisProject['ssh_url_to_repo']
command = shlex.split('git clone %s' % thisProjectURL)
resultCode = subprocess.Popen(command)
except Exception as e:
print("Error on %s: %s" % (thisProjectURL, e.strerror))
有一个工具叫做myrepos,它管理多个版本控制存储库。更新所有存储库只需要一个命令:
mr update
为了将所有gitlab项目注册到mr,这里有一个小python脚本。它需要安装包 python-gitlab:
import os
from subprocess import call
from gitlab import Gitlab
# Register a connection to a gitlab instance, using its URL and a user private token
gl = Gitlab('http://192.168.123.107', 'JVNSESs8EwWRx5yDxM5q')
groupsToSkip = ['aGroupYouDontWantToBeAdded']
gl.auth() # Connect to get the current user
gitBasePathRelative = "git/"
gitBasePathRelativeAbsolut = os.path.expanduser("~/" + gitBasePathRelative)
os.makedirs(gitBasePathRelativeAbsolut,exist_ok=True)
for p in gl.Project():
if not any(p.namespace.path in s for s in groupsToSkip):
pathToFolder = gitBasePathRelative + p.namespace.name + "/" + p.name
commandArray = ["mr", "config", pathToFolder, "checkout=git clone '" + p.ssh_url_to_repo + "' '" + p.name + "'"]
call(commandArray)
os.chdir(gitBasePathRelativeAbsolut)
call(["mr", "update"])
您可以在此处参考此 ruby 脚本:
https://gist.github.com/thegauraw/da2a3429f19f603cf1c9b3b09553728b
但是您需要确保您拥有组织 gitlab url 的 link(登录后看起来像:https://gitlab.example.com/api/v3/ for example organization) and private token (which looks like: QALWKQFAGZDWQYDGHADS and you can get in: https://gitlab.example.com/profile/account)。还要确保您安装了 httparty gem 或 gem install httparty
我为此构建了一个脚本(curl,git,需要 jq)。我们使用它并且它工作得很好:https://gist.github.com/JonasGroeger/1b5155e461036b557d0fb4b3307e1e75
要找出您的命名空间,最好快速检查 API:
curl "https://domain.com/api/v3/projects?private_token=$GITLAB_PRIVATE_TOKEN"
在那里,使用 "namespace.name" 作为您的组的 NAMESPACE
。
该脚本主要执行以下操作:
- 获取所有符合您的
PROJECT_SEARCH_PARAM
的项目
获取他们的 path
和 ssh_url_to_repo
2.1。如果目录 path
存在,cd 进入它并调用 git pull
2.2。如果目录path
不存在,调用git clone
这是另一个 bash 脚本示例,用于克隆组中的所有存储库。您需要安装的唯一依赖项是 jq (https://stedolan.github.io/jq/)。只需将脚本放入您要将项目克隆到的目录中。然后运行如下:
./myscript <group name> <private token> <gitlab url>
即
./myscript group1 abc123tyn234 http://yourserver.git.com
脚本:
#!/bin/bash
if command -v jq >/dev/null 2>&1; then
echo "jq parser found";
else
echo "this script requires the 'jq' json parser (https://stedolan.github.io/jq/).";
exit 1;
fi
if [ -z "" ]
then
echo "a group name arg is required"
exit 1;
fi
if [ -z "" ]
then
echo "an auth token arg is required. See /profile/account"
exit 1;
fi
if [ -z "" ]
then
echo "a gitlab URL is required."
exit 1;
fi
TOKEN="";
URL="/api/v3"
PREFIX="ssh_url_to_repo";
echo "Cloning all git projects in group ";
GROUP_ID=$(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups?search= | jq '.[].id')
echo "group id was $GROUP_ID";
curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$GROUP_ID/projects?per_page=100 | jq --arg p "$PREFIX" '.[] | .[$p]' | xargs -L1 git clone
一个更新的 Python 3 脚本,它使用 Gitlab 的最新 api 和正确的分页真正有效地实现了这一点:
import requests
import subprocess, shlex
import os
print('Starting getrepos process..')
key = '12345678901234567890' # your gitlab key
base_url = 'https://your.gitlab.url/api/v4/projects?simple=true&per_page=10&private_token='
url = base_url + key
base_dir = os.getcwd()
while True:
print('\n\nRetrieving from ' + url)
response = requests.get(url, verify = False)
projects = response.json()
for project in projects:
project_name = project['name']
project_path = project['namespace']['full_path']
project_url = project['ssh_url_to_repo']
os.chdir(base_dir)
print('\nProcessing %s...' % project_name)
try:
print('Moving into directory: %s' % project_path)
os.makedirs(project_path, exist_ok = True)
os.chdir(project_path)
cmd = shlex.split('git clone --mirror %s' % project_url)
subprocess.run(cmd)
except Exception as e:
print('Error: ' + e.strerror)
if 'next' not in response.links:
break
url = response.links['next']['url'].replace('127.0.0.1:9999', 'your.gitlab.url')
print('\nDone')
需要 requests 库(用于导航到页面链接)。
如果您对某些 shell 魔法没意见,这将克隆所有按组 ID 分组的存储库(您需要 jq 和并行)
seq 3 \
| parallel curl -s "'https://[gitlabUrl]/api/v4/projects?page={}&per_page=100&private_token=[privateToken]'
| jq '.[] | .ssh_url_to_repo, .name, .namespace.path'" \
| tr -d '"' \
| awk '{ printf "%s ", [=10=]; if (NR % 3 == 0) print " " }' \
| parallel --colsep ' ' 'mkdir -p {2} && git clone {1} {3}/{2}'
一个衬垫 curl
、jq
、tr
:
for repo in $(curl -s --header "PRIVATE-TOKEN: your_private_token" https://<your-host>/api/v4/groups/<group_id> | jq -r ".projects[].ssh_url_to_repo"); do git clone $repo; done;
对于 Gitlab.com 使用 https://gitlab.com/api/v4/groups/<group_id>
要包含子组 添加include_subgroups=true
查询参数 like
https://<your-host>/api/v4/groups/<group_id>?include_subgroups=true
另一种方法 Windows "Git Bash" 安装了有限的软件包:
#!/bin/bash
curl -o projects.json https://<GitLabUrl>/api/v4/projects?private_token=<YourToken>
i=0
while : ; do
echo "/$i/namespace/full_path" > jsonpointer
path=$(jsonpointer -f jsonpointer projects.json 2>/dev/null | tr -d '"')
[ -z "$path" ] && break
echo $path
if [ "${path%%/*}" == "<YourProject>" ]; then
[ ! -d "${path#*/}" ] && mkdir -p "${path#*/}"
echo "/$i/ssh_url_to_repo" > jsonpointer
url=$(jsonpointer -f jsonpointer projects.json 2>/dev/null | tr -d '"')
( cd "${path#*/}" ; git clone --mirror "$url" )
fi
let i+=1
done
rm -f projects.json jsonpointer
是的,这是可能的,这是代码。
先决条件:
pip 安装python-gitlab
#!/usr/bin/python3
import os
import sys
import gitlab
import subprocess
glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
groups = glab.groups.list()
groupname = sys.argv[2]
for group in groups:
if group.name == groupname:
projects = group.projects.list(all=True)
for repo in projects:
command = f'git clone {repo.ssh_url_to_repo}'
process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
output, _ = process.communicate()
process.wait()
示例:
- 创建 .py 文件(例如 gitlab-downloader.py)
- 从上面复制粘贴代码
- on Linux OS (or OSX) 对脚本文件做 chmod +x (ex. chmod +x gitlab-downloader.py)
- 运行 它有 3 个参数:Gitlab 主机名、组名、您的个人访问令牌(参见 https://gitlab.exmaple.com/profile/personal_access_tokens)
基于 Dmitriy 回答的备选方案——如果您要递归地克隆整个组树中的存储库。
#!/usr/bin/python3
import os
import sys
import gitlab
import subprocess
glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
groups = glab.groups.list()
root = sys.argv[2]
def visit(group):
name = group.name
real_group = glab.groups.get(group.id)
os.mkdir(name)
os.chdir(name)
clone(real_group.projects.list(all=True))
for child in real_group.subgroups.list():
visit(child)
os.chdir("../")
def clone(projects):
for repo in projects:
command = f'git clone {repo.ssh_url_to_repo}'
process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
output, _ = process.communicate()
process.wait()
glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
groups = glab.groups.list()
root = sys.argv[2]
for group in groups:
if group.name == root:
visit(group)
我已经编写了脚本来从特定组的 gitlab 中提取完整的代码库。
for pag in {1..3} // number of pages projects has span {per page 20 projects so if you have 50 projects loop should be 1..3}
do
curl -s http://gitlink/api/v4/groups/{groupName}/projects?page=$pag > url.txt
grep -o '"ssh_url_to_repo": *"[^"]*"' url.txt | grep -o '"[^"]*"$' | while read -r line ; do
l1=${line%?}
l2=${l1:1}
echo "$l2"
git clone $l2
done
done
作为对@Kosrat D. Ahmad 的回应,我遇到了同样的问题(嵌套子组 - 我的子组实际上有 5 层深!)
#!/bin/bash
URL="https://mygitlaburl/api/v4"
TOKEN="mytoken"
function check_subgroup {
echo "checking $gid"
if [[ $(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$gid/subgroups/ | jq .[].id -r) != "" ]]; then
for gid in $(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$gid/subgroups/ | jq .[].id -r)
do
check_subgroup
done
else
echo $gid >> top_level
fi
}
> top_level #empty file
> repos #empty file
for gid in $(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/ | jq .[].id -r)
do
check_subgroup
done
# This is necessary because there will be duplicates if each group has multiple nested groups. I'm sure there's a more elegant way to do this though!
for gid in $(sort top_level | uniq)
do
curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$gid | jq .projects[].http_url_to_repo -r >> repos
done
while read repo; do
git clone $repo
done <repos
rm top_level
rm repos
注意:我使用 jq .projects[].http_url_to_repo 如果您愿意,可以将其替换为 .ssh_url_to_repo。
或者剥离 rm 并单独查看文件以检查输出等。
诚然,这将克隆所有内容,但您可以根据需要对其进行调整。
资源:https://docs.gitlab.com/ee/api/groups.html#list-a-groups-subgroups
我为此创建了一个工具:https://github.com/ezbz/gitlabber,您可以使用 glob/regex 表达式来 select groups/subgroups 您想要克隆。
假设您的顶级组名为 MyGroup
,并且您想将其下的所有项目克隆到 ~/GitlabRoot
,您可以使用以下命令:
gitlabber -t <personal access token> -u <gitlab url> -i '/MyGroup**' ~/GitlabRoot
这是一个 Java 版本,使用 gitlab4j 和访问令牌和 git 命令对我有用。
我 运行 在 Windows 和 Mac 上使用它并且它有效。对于 Windows,只需在 .exec()
中的 'git clone' 之前添加 'cmd /c'
void doClone() throws Exception {
try (GitLabApi gitLabApi = new GitLabApi("[your-git-host].com/", "[your-access-token]");) {
List<Project> projects = gitLabApi.getGroupApi().getProjects("[your-group-name]");
projects.forEach(p -> {
try {
Runtime.getRuntime().exec("git clone " + p.getSshUrlToRepo(), null, new File("[path-to-folder-to-clone-projects-to]"));
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
修改了@Hot Diggity 的回答。
import json
import subprocess, shlex
allProjects = urlopen("https://gitlab.com/api/v4/projects?private_token=token&membership=true&per_page=1000")
allProjectsDict = json.loads(allProjects.read().decode())
for thisProject in allProjectsDict:
try:
thisProjectURL = thisProject['ssh_url_to_repo']
path = thisProject['path_with_namespace'].replace('/', '-')
command = shlex.split('git clone %s %s' % (thisProjectURL, path))
p = subprocess.Popen(command)
p_status = p.wait()
except Exception as e:
print("Error on %s: %s" % (thisProjectURL, e.strerror))
对于 powershell(替换并传入来自 gitlab 的私有令牌(或对其进行硬编码)):
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url="https://<gitlab host>/api/v4/groups/<group>/projects?
simple=1&include_subgroups=true&private_token="+$args[0]
$req = Invoke-WebRequest $url | ConvertFrom-Json
foreach( $project in $req ) {
Start-Process git -ArgumentList "clone", $project.ssh_url_to_repo
}
很多好的答案,但这是我的看法。在以下情况下使用它:
- 想要并行克隆所有内容
- 将您的 ssh 密钥配置为无需输入密码即可从服务器克隆
- 不想创建访问令牌
- 正在使用有限的 shell 喜欢 git bash
因此,使用您的浏览器访问 https://gitlab.<gitlabserver>/api/v4/groups/<group name>?per_page=1000
下载包含所有项目信息的 json 并 将其保存为名为 group.json
的文件。
现在只需 运行 同一目录中的这个简单命令:
egrep -o 'git@[^"]+.git' group.json|xargs -n 1 -P 8 git clone
增加 -P 8
中的数字以更改并行进程的数量。
如果 <group name>
有空格或重音字符,请注意它必须 url 编码。
如果要自动下载,最简单的验证方法是在GitLab/GitHub中生成访问令牌并将其放入url:https://user:access_toke@mygitlab.net/api/v4/groups/<group name>?per_page=1000
.
使用 curl、jq 和 tr 以及前面描述的相同方法,但用于 20 多个项目:
for repo in $(curl --header "PRIVATE-TOKEN:<Private-Token>" -s "https://<your-host>/api/v4/groups/<group-id>/projects?include_subgroups=true&per_page=100&page=n" | jq '.[].ssh_url_to_repo' | tr -d '"'); do git clone $repo; done;
对于 Gitlab.com 使用 https://gitlab.com/api/v4/groups/[group-id]/projects
只需要迭代改变页码。
Dinesh Balasubramanian 响应的一个班轮 python3 版本。
我只是因为缺少jq才做这个的,只有python3(请求)
import requests,os; [os.system('git clone {[http_url_to_repo]}'.format(p)) for p in requests.get('https://<<REPO_URL>>/api/v4/groups/<<GROUP_ID>>',headers={'PRIVATE-TOKEN':'<<YOUR_PRIVATE_TOKEN>>'},verify=False).json()['projects']]
替换<>、<>和<>
这是 @ruben-lohaus post 中的 oneliner 的一个改进版本。
- 它最多适用于组中的 100 个回购协议。
- 将克隆组中的每个存储库,包括路径。
要求:
- grep
- jq
- 卷曲
GITLAB_URL="https://gitlab.mydomain.local/api/v4/groups/1141/projects?include_subgroups=true&per_page=100&page=0"
GITLAB_TOKEN="ABCDEFABCDef_5n"
REPOS=$(curl --header "PRIVATE-TOKEN:${GITLAB_TOKEN}" -s "${GITLAB_URL}" | jq -r '.[].ssh_url_to_repo')
for repo in $(echo -e "$REPOS")
do git clone $repo $(echo $repo | grep -oP '(?<=:).*(?=.git$)')
done
基于 ,使用个人访问令牌而不是 SSH 到 git 克隆。
一个带 curl
、jq
、tr
的衬垫
没有子组:
for repo in $(curl -s --header "PRIVATE-TOKEN: <private_token>" https://<your-host>/api/v4/groups/<group-name> | jq ".projects[]".http_url_to_repo | tr -d '"' | cut -c 9-); do git clone https://token:<private_token>@$repo; done;
包括子组:
for repo in $(curl -s --header "PRIVATE-TOKEN: <private_token>" "https://<your-host>/api/v4/groups/<group-name>/projects?include_subgroups=true&per_page=1000" | jq ".[]".http_url_to_repo | tr -d '"' | cut -c 9-); do git clone https://token:<private_token>@$repo; done;
请注意,curl 的 private_token
必须拥有 API
权限。 git clone
的 private_token
必须至少拥有 read_repository
权限。它可以是相同的令牌(如果它具有 API
权限),但也可以是 2 个不同的令牌
我的理解是所有的答案都只允许你clone repos,不包括issues、boards、其他设置等,如有错误请指正。
我觉得如果要备份多个项目的所有数据,目的是不仅要包括回购,还要包括其他数据,这些数据可能和回购一样重要。
Self-hosted Gitlab实例可以在官方支持下实现这一点,参见backup and restore GitLab。
在我的 GitLab 存储库中,我有一个包含 20 个项目的组。我想一次克隆所有项目。这可能吗?
不是真的,除非:
你有一个第 21 个项目引用了其他 20 个项目 submodules。
(在这种情况下,一个克隆后跟一个git submodule update --init
就足以克隆并签出所有 20 个项目)或者您以某种方式列出您有权访问的项目 (GitLab API for projects),然后循环该结果以克隆每个项目(这意味着可以编写脚本,然后作为“一个”执行命令)
自 2015 年以来,Jay Gabez mentions gabrie30/ghorg
ghorg
allows you to quickly clone all of an org's or user's repos into a single directory.
用法:
$ ghorg clone someorg
$ ghorg clone someuser --clone-type=user --protocol=ssh --branch=develop
$ ghorg clone gitlab-org --scm=gitlab --namespace=gitlab-org/security-products
$ ghorg clone --help
另外 (2020):https://github.com/ezbz/gitlabber
usage: gitlabber [-h] [-t token] [-u url] [--debug] [-p]
[--print-format {json,yaml,tree}] [-i csv] [-x csv]
[--version]
[dest]
Gitlabber - clones or pulls entire groups/projects tree from gitlab
这是 Python 3 中的示例:
from urllib.request import urlopen
import json
import subprocess, shlex
allProjects = urlopen("https://[yourServer:port]/api/v4/projects?private_token=[yourPrivateTokenFromUserProfile]&per_page=100000")
allProjectsDict = json.loads(allProjects.read().decode())
for thisProject in allProjectsDict:
try:
thisProjectURL = thisProject['ssh_url_to_repo']
command = shlex.split('git clone %s' % thisProjectURL)
resultCode = subprocess.Popen(command)
except Exception as e:
print("Error on %s: %s" % (thisProjectURL, e.strerror))
有一个工具叫做myrepos,它管理多个版本控制存储库。更新所有存储库只需要一个命令:
mr update
为了将所有gitlab项目注册到mr,这里有一个小python脚本。它需要安装包 python-gitlab:
import os
from subprocess import call
from gitlab import Gitlab
# Register a connection to a gitlab instance, using its URL and a user private token
gl = Gitlab('http://192.168.123.107', 'JVNSESs8EwWRx5yDxM5q')
groupsToSkip = ['aGroupYouDontWantToBeAdded']
gl.auth() # Connect to get the current user
gitBasePathRelative = "git/"
gitBasePathRelativeAbsolut = os.path.expanduser("~/" + gitBasePathRelative)
os.makedirs(gitBasePathRelativeAbsolut,exist_ok=True)
for p in gl.Project():
if not any(p.namespace.path in s for s in groupsToSkip):
pathToFolder = gitBasePathRelative + p.namespace.name + "/" + p.name
commandArray = ["mr", "config", pathToFolder, "checkout=git clone '" + p.ssh_url_to_repo + "' '" + p.name + "'"]
call(commandArray)
os.chdir(gitBasePathRelativeAbsolut)
call(["mr", "update"])
您可以在此处参考此 ruby 脚本: https://gist.github.com/thegauraw/da2a3429f19f603cf1c9b3b09553728b
但是您需要确保您拥有组织 gitlab url 的 link(登录后看起来像:https://gitlab.example.com/api/v3/ for example organization) and private token (which looks like: QALWKQFAGZDWQYDGHADS and you can get in: https://gitlab.example.com/profile/account)。还要确保您安装了 httparty gem 或 gem install httparty
我为此构建了一个脚本(curl,git,需要 jq)。我们使用它并且它工作得很好:https://gist.github.com/JonasGroeger/1b5155e461036b557d0fb4b3307e1e75
要找出您的命名空间,最好快速检查 API:
curl "https://domain.com/api/v3/projects?private_token=$GITLAB_PRIVATE_TOKEN"
在那里,使用 "namespace.name" 作为您的组的 NAMESPACE
。
该脚本主要执行以下操作:
- 获取所有符合您的
PROJECT_SEARCH_PARAM
的项目
获取他们的
path
和ssh_url_to_repo
2.1。如果目录
path
存在,cd 进入它并调用git pull
2.2。如果目录
path
不存在,调用git clone
这是另一个 bash 脚本示例,用于克隆组中的所有存储库。您需要安装的唯一依赖项是 jq (https://stedolan.github.io/jq/)。只需将脚本放入您要将项目克隆到的目录中。然后运行如下:
./myscript <group name> <private token> <gitlab url>
即
./myscript group1 abc123tyn234 http://yourserver.git.com
脚本:
#!/bin/bash
if command -v jq >/dev/null 2>&1; then
echo "jq parser found";
else
echo "this script requires the 'jq' json parser (https://stedolan.github.io/jq/).";
exit 1;
fi
if [ -z "" ]
then
echo "a group name arg is required"
exit 1;
fi
if [ -z "" ]
then
echo "an auth token arg is required. See /profile/account"
exit 1;
fi
if [ -z "" ]
then
echo "a gitlab URL is required."
exit 1;
fi
TOKEN="";
URL="/api/v3"
PREFIX="ssh_url_to_repo";
echo "Cloning all git projects in group ";
GROUP_ID=$(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups?search= | jq '.[].id')
echo "group id was $GROUP_ID";
curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$GROUP_ID/projects?per_page=100 | jq --arg p "$PREFIX" '.[] | .[$p]' | xargs -L1 git clone
一个更新的 Python 3 脚本,它使用 Gitlab 的最新 api 和正确的分页真正有效地实现了这一点:
import requests
import subprocess, shlex
import os
print('Starting getrepos process..')
key = '12345678901234567890' # your gitlab key
base_url = 'https://your.gitlab.url/api/v4/projects?simple=true&per_page=10&private_token='
url = base_url + key
base_dir = os.getcwd()
while True:
print('\n\nRetrieving from ' + url)
response = requests.get(url, verify = False)
projects = response.json()
for project in projects:
project_name = project['name']
project_path = project['namespace']['full_path']
project_url = project['ssh_url_to_repo']
os.chdir(base_dir)
print('\nProcessing %s...' % project_name)
try:
print('Moving into directory: %s' % project_path)
os.makedirs(project_path, exist_ok = True)
os.chdir(project_path)
cmd = shlex.split('git clone --mirror %s' % project_url)
subprocess.run(cmd)
except Exception as e:
print('Error: ' + e.strerror)
if 'next' not in response.links:
break
url = response.links['next']['url'].replace('127.0.0.1:9999', 'your.gitlab.url')
print('\nDone')
需要 requests 库(用于导航到页面链接)。
如果您对某些 shell 魔法没意见,这将克隆所有按组 ID 分组的存储库(您需要 jq 和并行)
seq 3 \
| parallel curl -s "'https://[gitlabUrl]/api/v4/projects?page={}&per_page=100&private_token=[privateToken]'
| jq '.[] | .ssh_url_to_repo, .name, .namespace.path'" \
| tr -d '"' \
| awk '{ printf "%s ", [=10=]; if (NR % 3 == 0) print " " }' \
| parallel --colsep ' ' 'mkdir -p {2} && git clone {1} {3}/{2}'
一个衬垫 curl
、jq
、tr
:
for repo in $(curl -s --header "PRIVATE-TOKEN: your_private_token" https://<your-host>/api/v4/groups/<group_id> | jq -r ".projects[].ssh_url_to_repo"); do git clone $repo; done;
对于 Gitlab.com 使用 https://gitlab.com/api/v4/groups/<group_id>
要包含子组 添加include_subgroups=true
查询参数 like
https://<your-host>/api/v4/groups/<group_id>?include_subgroups=true
另一种方法 Windows "Git Bash" 安装了有限的软件包:
#!/bin/bash
curl -o projects.json https://<GitLabUrl>/api/v4/projects?private_token=<YourToken>
i=0
while : ; do
echo "/$i/namespace/full_path" > jsonpointer
path=$(jsonpointer -f jsonpointer projects.json 2>/dev/null | tr -d '"')
[ -z "$path" ] && break
echo $path
if [ "${path%%/*}" == "<YourProject>" ]; then
[ ! -d "${path#*/}" ] && mkdir -p "${path#*/}"
echo "/$i/ssh_url_to_repo" > jsonpointer
url=$(jsonpointer -f jsonpointer projects.json 2>/dev/null | tr -d '"')
( cd "${path#*/}" ; git clone --mirror "$url" )
fi
let i+=1
done
rm -f projects.json jsonpointer
是的,这是可能的,这是代码。
先决条件:
pip 安装python-gitlab
#!/usr/bin/python3
import os
import sys
import gitlab
import subprocess
glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
groups = glab.groups.list()
groupname = sys.argv[2]
for group in groups:
if group.name == groupname:
projects = group.projects.list(all=True)
for repo in projects:
command = f'git clone {repo.ssh_url_to_repo}'
process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
output, _ = process.communicate()
process.wait()
示例:
- 创建 .py 文件(例如 gitlab-downloader.py)
- 从上面复制粘贴代码
- on Linux OS (or OSX) 对脚本文件做 chmod +x (ex. chmod +x gitlab-downloader.py)
- 运行 它有 3 个参数:Gitlab 主机名、组名、您的个人访问令牌(参见 https://gitlab.exmaple.com/profile/personal_access_tokens)
基于 Dmitriy 回答的备选方案——如果您要递归地克隆整个组树中的存储库。
#!/usr/bin/python3
import os
import sys
import gitlab
import subprocess
glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
groups = glab.groups.list()
root = sys.argv[2]
def visit(group):
name = group.name
real_group = glab.groups.get(group.id)
os.mkdir(name)
os.chdir(name)
clone(real_group.projects.list(all=True))
for child in real_group.subgroups.list():
visit(child)
os.chdir("../")
def clone(projects):
for repo in projects:
command = f'git clone {repo.ssh_url_to_repo}'
process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
output, _ = process.communicate()
process.wait()
glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
groups = glab.groups.list()
root = sys.argv[2]
for group in groups:
if group.name == root:
visit(group)
我已经编写了脚本来从特定组的 gitlab 中提取完整的代码库。
for pag in {1..3} // number of pages projects has span {per page 20 projects so if you have 50 projects loop should be 1..3}
do
curl -s http://gitlink/api/v4/groups/{groupName}/projects?page=$pag > url.txt
grep -o '"ssh_url_to_repo": *"[^"]*"' url.txt | grep -o '"[^"]*"$' | while read -r line ; do
l1=${line%?}
l2=${l1:1}
echo "$l2"
git clone $l2
done
done
作为对@Kosrat D. Ahmad 的回应,我遇到了同样的问题(嵌套子组 - 我的子组实际上有 5 层深!)
#!/bin/bash
URL="https://mygitlaburl/api/v4"
TOKEN="mytoken"
function check_subgroup {
echo "checking $gid"
if [[ $(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$gid/subgroups/ | jq .[].id -r) != "" ]]; then
for gid in $(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$gid/subgroups/ | jq .[].id -r)
do
check_subgroup
done
else
echo $gid >> top_level
fi
}
> top_level #empty file
> repos #empty file
for gid in $(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/ | jq .[].id -r)
do
check_subgroup
done
# This is necessary because there will be duplicates if each group has multiple nested groups. I'm sure there's a more elegant way to do this though!
for gid in $(sort top_level | uniq)
do
curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$gid | jq .projects[].http_url_to_repo -r >> repos
done
while read repo; do
git clone $repo
done <repos
rm top_level
rm repos
注意:我使用 jq .projects[].http_url_to_repo 如果您愿意,可以将其替换为 .ssh_url_to_repo。
或者剥离 rm 并单独查看文件以检查输出等。
诚然,这将克隆所有内容,但您可以根据需要对其进行调整。
资源:https://docs.gitlab.com/ee/api/groups.html#list-a-groups-subgroups
我为此创建了一个工具:https://github.com/ezbz/gitlabber,您可以使用 glob/regex 表达式来 select groups/subgroups 您想要克隆。
假设您的顶级组名为 MyGroup
,并且您想将其下的所有项目克隆到 ~/GitlabRoot
,您可以使用以下命令:
gitlabber -t <personal access token> -u <gitlab url> -i '/MyGroup**' ~/GitlabRoot
这是一个 Java 版本,使用 gitlab4j 和访问令牌和 git 命令对我有用。
我 运行 在 Windows 和 Mac 上使用它并且它有效。对于 Windows,只需在 .exec()
中的 'git clone' 之前添加 'cmd /c' void doClone() throws Exception {
try (GitLabApi gitLabApi = new GitLabApi("[your-git-host].com/", "[your-access-token]");) {
List<Project> projects = gitLabApi.getGroupApi().getProjects("[your-group-name]");
projects.forEach(p -> {
try {
Runtime.getRuntime().exec("git clone " + p.getSshUrlToRepo(), null, new File("[path-to-folder-to-clone-projects-to]"));
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
修改了@Hot Diggity 的回答。
import json
import subprocess, shlex
allProjects = urlopen("https://gitlab.com/api/v4/projects?private_token=token&membership=true&per_page=1000")
allProjectsDict = json.loads(allProjects.read().decode())
for thisProject in allProjectsDict:
try:
thisProjectURL = thisProject['ssh_url_to_repo']
path = thisProject['path_with_namespace'].replace('/', '-')
command = shlex.split('git clone %s %s' % (thisProjectURL, path))
p = subprocess.Popen(command)
p_status = p.wait()
except Exception as e:
print("Error on %s: %s" % (thisProjectURL, e.strerror))
对于 powershell(替换并传入来自 gitlab 的私有令牌(或对其进行硬编码)):
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url="https://<gitlab host>/api/v4/groups/<group>/projects?
simple=1&include_subgroups=true&private_token="+$args[0]
$req = Invoke-WebRequest $url | ConvertFrom-Json
foreach( $project in $req ) {
Start-Process git -ArgumentList "clone", $project.ssh_url_to_repo
}
很多好的答案,但这是我的看法。在以下情况下使用它:
- 想要并行克隆所有内容
- 将您的 ssh 密钥配置为无需输入密码即可从服务器克隆
- 不想创建访问令牌
- 正在使用有限的 shell 喜欢 git bash
因此,使用您的浏览器访问 https://gitlab.<gitlabserver>/api/v4/groups/<group name>?per_page=1000
下载包含所有项目信息的 json 并 将其保存为名为 group.json
的文件。
现在只需 运行 同一目录中的这个简单命令:
egrep -o 'git@[^"]+.git' group.json|xargs -n 1 -P 8 git clone
增加 -P 8
中的数字以更改并行进程的数量。
如果 <group name>
有空格或重音字符,请注意它必须 url 编码。
如果要自动下载,最简单的验证方法是在GitLab/GitHub中生成访问令牌并将其放入url:https://user:access_toke@mygitlab.net/api/v4/groups/<group name>?per_page=1000
.
使用 curl、jq 和 tr 以及前面描述的相同方法,但用于 20 多个项目:
for repo in $(curl --header "PRIVATE-TOKEN:<Private-Token>" -s "https://<your-host>/api/v4/groups/<group-id>/projects?include_subgroups=true&per_page=100&page=n" | jq '.[].ssh_url_to_repo' | tr -d '"'); do git clone $repo; done;
对于 Gitlab.com 使用 https://gitlab.com/api/v4/groups/[group-id]/projects
只需要迭代改变页码。
Dinesh Balasubramanian 响应的一个班轮 python3 版本。
我只是因为缺少jq才做这个的,只有python3(请求)
import requests,os; [os.system('git clone {[http_url_to_repo]}'.format(p)) for p in requests.get('https://<<REPO_URL>>/api/v4/groups/<<GROUP_ID>>',headers={'PRIVATE-TOKEN':'<<YOUR_PRIVATE_TOKEN>>'},verify=False).json()['projects']]
替换<
这是 @ruben-lohaus post 中的 oneliner 的一个改进版本。
- 它最多适用于组中的 100 个回购协议。
- 将克隆组中的每个存储库,包括路径。
要求:
- grep
- jq
- 卷曲
GITLAB_URL="https://gitlab.mydomain.local/api/v4/groups/1141/projects?include_subgroups=true&per_page=100&page=0"
GITLAB_TOKEN="ABCDEFABCDef_5n"
REPOS=$(curl --header "PRIVATE-TOKEN:${GITLAB_TOKEN}" -s "${GITLAB_URL}" | jq -r '.[].ssh_url_to_repo')
for repo in $(echo -e "$REPOS")
do git clone $repo $(echo $repo | grep -oP '(?<=:).*(?=.git$)')
done
基于
一个带 curl
、jq
、tr
没有子组:
for repo in $(curl -s --header "PRIVATE-TOKEN: <private_token>" https://<your-host>/api/v4/groups/<group-name> | jq ".projects[]".http_url_to_repo | tr -d '"' | cut -c 9-); do git clone https://token:<private_token>@$repo; done;
包括子组:
for repo in $(curl -s --header "PRIVATE-TOKEN: <private_token>" "https://<your-host>/api/v4/groups/<group-name>/projects?include_subgroups=true&per_page=1000" | jq ".[]".http_url_to_repo | tr -d '"' | cut -c 9-); do git clone https://token:<private_token>@$repo; done;
请注意,curl 的 private_token
必须拥有 API
权限。 git clone
的 private_token
必须至少拥有 read_repository
权限。它可以是相同的令牌(如果它具有 API
权限),但也可以是 2 个不同的令牌
我的理解是所有的答案都只允许你clone repos,不包括issues、boards、其他设置等,如有错误请指正。
我觉得如果要备份多个项目的所有数据,目的是不仅要包括回购,还要包括其他数据,这些数据可能和回购一样重要。
Self-hosted Gitlab实例可以在官方支持下实现这一点,参见backup and restore GitLab。