如何在GitLab中一次克隆一个组的所有项目?

Doo*_*oon 48 git gitlab

在我的GitLab存储库中,我有一个包含20个项目的组.我想一次克隆所有项目.那可能吗?

Din*_*ian 40

一个带卷曲、jq、tr 的衬垫

for repo in $(curl -s --header "PRIVATE-TOKEN: your_private_token" https://<your-host>/api/v4/groups/<group_id> | jq ".projects[].ssh_url_to_repo" | tr -d '"'); do git clone $repo; done;
Run Code Online (Sandbox Code Playgroud)

对于 Gitlab.com使用https://gitlab.com/api/v4/groups/<group_id>

要包含子组,请添加include_subgroups=true查询参数,例如

https://<your-host>/api/v4/groups/<group_id>?include_subgroups=true
Run Code Online (Sandbox Code Playgroud)

  • 使用“include_subgroups=true”对我不起作用。所以我使用了以下效果很好的方法: `for repo in $(curl -s --header "PRIVATE-TOKEN: &lt;my-token&gt;" https://gitlab.com/api/v4/groups/&lt;group-id &gt;/projects\?include_subgroups\=true | jq ".[].ssh_url_to_repo" | tr -d '"'); 执行 git clone $repo; 完成;` (9认同)
  • 即使添加了“include_subgroups=true”之后,对于子组也不起作用。然而,@Ruben 的答案效果很好。API URL 中需要包含“/projects”。 (4认同)
  • 这仅提供组文件夹中的项目。如何获取子组(子文件夹)中的项目? (3认同)
  • 又好又简单!迄今为止最好的一次性答案。值得一提的是,这仅适用于“bash”,并且必须安装“curl”和“jq”。 (2认同)

小智 24

这是Python 3中的一个例子:

from urllib.request import urlopen
import json
import subprocess, shlex

allProjects     = urlopen("http://[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))
Run Code Online (Sandbox Code Playgroud)


Von*_*onC 19

不是,除非:

  • 你有一个第21个项目,它引用其他20个作为子模块.
    (在这种情况下,克隆后跟a git submodule update --init就足以克隆并检出所有20个项目)

  • 或者以某种方式列出您有权访问的项目(项目的GitLab API),并循环该结果以克隆每个项目(意味着可以编写脚本,然后作为"一个"命令执行)

  • [ghorg](https://github.com/gabrie30/ghorg) 是一个小型 cli,可以为您执行此操作 (3认同)
  • @JayGabez 谢谢。我已将您的评论包含在答案中以获得更多可见性。 (2认同)
  • glab cli 的工作方式就像一个魅力, $ glab repo clone -g &lt;group_id&gt; -p --paginate (2认同)

nev*_*ves 8

很多好的答案,但这是我的看法。如果您符合以下条件,请使用它:

  • 想要并行克隆所有内容
  • 将 ssh 密钥配置为从服务器克隆而无需输入密码
  • 不想费心创建访问令牌
  • 正在使用像 git bash 这样的有限 shell(不带jq

因此,使用浏览器下载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 
Run Code Online (Sandbox Code Playgroud)

增加 in 的数量-P 8可更改并行进程的数量。如果您有超过 1000 个存储库,请增加perpage=.

如果<group name>有空格或重音字符,请注意它必须是 url 编码的。

如果您想自动下载,最简单的身份验证方法是在 GitLab/GitHub 中生成访问令牌并将其放在 url 中:https://user:access_toke@mygitlab.net/api/v4/groups/<group name>?per_page=1000

@jocullin 在评论中给出了一个很好的提示,可以下载子组。只需添加&include_subgroups=true到上面的组 url 即可。

  • 这种方法使导出一组项目变得简单。如果您有子组,即父/子,则 `&lt;group name&gt;` 将是 url 编码值,即 `parent%2Fchild` (2认同)

Ben*_*ikt 7

有一个名为myrepos的工具,它管理多个版本控制存储库.更新所有存储库只需要一个命令:

mr update
Run Code Online (Sandbox Code Playgroud)

为了将所有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"])
Run Code Online (Sandbox Code Playgroud)


Jon*_*ger 7

我为此构建了一个脚本(curl,git,jq).我们使用它并且它工作得很好:https://gist.github.com/JonasGroeger/1b5155e461036b557d0fb4b3307e1e75

要找到您的命名空间,最好快速检查API:

curl "https://domain.com/api/v3/projects?private_token=$GITLAB_PRIVATE_TOKEN"
Run Code Online (Sandbox Code Playgroud)

在那里,使用"namespace.name"作为NAMESPACE您的组.

该脚本基本上做:

  1. 获取与您匹配的所有项目 PROJECT_SEARCH_PARAM
  2. 得到他们的pathssh_url_to_repo

    2.1.如果目录path存在,请进入并调用git pull

    2.2.如果目录path不存在,请致电git clone


use*_*280 7

我为此创建了一个工具: https: //github.com/ezbz/gitlabber,您可以使用 glob/regex 表达式来选择您想要克隆的组/子组。

假设您的顶级组被调用MyGroup,并且您想要克隆其下的所有项目,~/GitlabRoot您可以使用以下命令:

    gitlabber -t <personal access token> -u <gitlab url> -i '/MyGroup**' ~/GitlabRoot
Run Code Online (Sandbox Code Playgroud)


pbu*_*eit 6

这是bash脚本的另一个示例,用于克隆组中的所有存储库。您需要安装的唯一依赖项是jq(https://stedolan.github.io/jq/)。只需将脚本放入要克隆项目的目录中即可。然后如下运行:

./myscript <group name> <private token> <gitlab url>
Run Code Online (Sandbox Code Playgroud)

./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 "$1" ]
  then
    echo "a group name arg is required"
    exit 1;
fi

if [ -z "$2" ]
  then
    echo "an auth token arg is required. See $3/profile/account"
    exit 1;
fi

if [ -z "$3" ]
  then
    echo "a gitlab URL is required."
    exit 1;
fi

TOKEN="$2";
URL="$3/api/v3"
PREFIX="ssh_url_to_repo";

echo "Cloning all git projects in group $1";

GROUP_ID=$(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups?search=$1 | 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
Run Code Online (Sandbox Code Playgroud)


小智 6

是的,这是可能的,这是代码。

先决条件:

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()
Run Code Online (Sandbox Code Playgroud)

例子:

  • 创建 .py 文件(例如 gitlab-downloader.py)
  • 从上面复制粘贴代码
  • 在 Linux 操作系统(或 OSX)上对脚本文件执行 chmod +x(例如 chmod +x gitlab-downloader.py)
  • 使用 3 个参数运行它:Gitlab 主机名、组名、您的个人访问令牌(请参阅https://gitlab.exmaple.com/profile/personal_access_tokens


小智 6

使用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;
Run Code Online (Sandbox Code Playgroud)

对于 Gitlab.com,请使用https://gitlab.com/api/v4/groups/[group-id]/projects

只需要迭代改变页码。


for*_*nsa 5

一个更新的 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')
Run Code Online (Sandbox Code Playgroud)

需要请求库(用于导航到页面链接)。


Mos*_*yeb 5

如果您对某些 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 ", $0; if (NR % 3 == 0) print " " }'                    \
| parallel --colsep ' ' 'mkdir -p {2} && git clone {1} {3}/{2}'
Run Code Online (Sandbox Code Playgroud)