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

时间:2015-03-17 12:46:01

标签: git gitlab

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

20 个答案:

答案 0 :(得分:22)

这是Python 3中的一个例子:

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

allProjects     = urlopen("http://[yourServer:port]/api/v3/projects/all?private_token=[yourPrivateTokenFromUserProfile]")
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))

答案 1 :(得分:14)

不是,除非:

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

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

答案 2 :(得分:7)

有一个名为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"])

答案 3 :(得分:7)

我为此构建了一个脚本(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

该脚本基本上可以:

  1. 获取与PROJECT_SEARCH_PARAM
  2. 匹配的所有项目
  3. 获取pathssh_url_to_repo

    2.1。如果目录path存在,请插入其中并致电git pull

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

答案 4 :(得分:4)

以下是克隆组中所有repos的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 "$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

答案 5 :(得分:4)

如果您对某些shell防护还可以,这将克隆按其组ID分组的所有存储库(您需要jq和parallel)

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}'

答案 6 :(得分:3)

这是一个对我有用的 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();
            }
        });
    }
}

答案 7 :(得分:2)

可以,这是代码。

先决条件:

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)
  • 从上方复制粘贴代码
  • 在Linux OS(或OSX)上,对脚本文件执行chmod + x(例如chmod + x gitlab-downloader.py)
  • 使用3个参数运行它:Gitlab主机名,组名,您的个人访问令牌(请参见https://gitlab.exmaple.com/profile/personal_access_tokens

答案 8 :(得分:2)

一个带有卷曲,jq和tr的衬里

for repo in $(curl "https://<your-host>/api/v4/groups/<group_id>?private_token=<your_private_token>" | jq .projects[].ssh_url_to_repo | tr -d '"'); do git clone $repo; done;```

答案 9 :(得分:2)

您可以在此处参考此ruby脚本: https://gist.github.com/thegauraw/da2a3429f19f603cf1c9b3b09553728b

但是你需要确保你有组织gitlab url的链接(看起来像https://gitlab.example.com/api/v3/,例如组织)和私人令牌(看起来像:QALWKQFAGZDWQYDGHADS,你可以进入:{{ 3}}一旦你登录了)。另外,请确保安装了httparty gem或gem install httparty

答案 10 :(得分:1)

经过更新的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库(用于导航到页面链接)。

答案 11 :(得分:1)

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

假设您的顶级组名为MyGroup,并且要将其下的所有项目克隆到~/GitlabRoot,则可以使用以下命令:

    gitlabber -t <personal access token> -u <gitlab url> -i '/MyGroup**' ~/GitlabRoot

答案 12 :(得分:1)

很多好的答案,但这是我的看法。在以下情况下使用它:

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

因此,使用您的浏览器访问 https://gitlab.<gitlabserver>/api/v4/groups/<group name>?per_page=100 下载包含所有项目信息的 json 并将其保存为 group.json。现在只需运行这个简单的命令:

egrep -o  'git@[^"]+.git' group.json|xargs -n 1 -P 8 git clone 

答案 13 :(得分:1)

使用 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

只需要迭代改变页码。

答案 14 :(得分:0)

使用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

答案 15 :(得分:0)

基于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)

答案 16 :(得分:0)

我编写了脚本,以从gitlab提取特定组的完整代码库。

for pag in {1..3} // number of pages projects has span {per page 20 projects so if you have 50 pages 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

答案 17 :(得分:0)

在回应@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

答案 18 :(得分:0)

修改了@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))

答案 19 :(得分:0)

对于 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
}