如何一次从GitHub克隆所有存储库?


97

我有一个公司GitHub帐户,我想备份其中的所有存储库,以考虑可能出于自动化目的而创建的所有新内容。我希望是这样的:

git clone git@github.com:company/*.git 

或类似的方法可行,但似乎不喜欢通配符。

Git中是否有一种方法可以进行克隆,然后假定拥有适当的权限就提取所有内容?


2
好问题。以及如何通过拉动使它们保持同步?答案对拉动有用吗?
nealmcb 2015年

我们需要一个python解决方案,对于那些不那么擅长node或ruby的人;)或github应该阅读并对此表示同情,并为此提供一个简单的Web界面..
nealmcb 2015年

Answers:


52

我认为不可能那样做。最好的选择是使用API​​查找并遍历组织的存储库列表。

试试这个:

  • 通过转到帐户设置->应用程序来创建API令牌
  • 致电至: http://${GITHUB_BASE_URL}/api/v3/orgs/${ORG_NAME}/repos?access_token=${ACCESS_TOKEN}
  • 响应将是对象的JSON数组。每个对象都将包含有关该组织下一个存储库的信息。我认为,就您而言,您将专门寻找该ssh_url物业。
  • 然后git clone每个ssh_url

这需要一些额外的工作,但是GitHub必须具有正确的身份验证。


我创建了API令牌,并且从调用中获取了输出,但是看不到任何引用我对我们的存储库或'ssh_url'字符串的了解的内容。我怀疑我没有正确拨打电话。 curl -i https://github.com/api/v3/orgs/company/repos?access_token=<token>
numb3rs1x

这是GitHub Enterprise帐户还是github.com?
Thomas Kelley

1
啊,我误会了你。我以为是企业帐户。相反https://github.com/api/v3/,请尝试https://api.github.com/
Thomas Kelley

1
而且我不确定您的特定公司的成立方式,但是如果它是“用户”而不是“组织”,那么您将想要使用/users/${COMPANY}/repos路径而不是/orgs/${COMPANY}/repos
Thomas Kelley

1
每个GitHub:请改用Authorization HTTP标头,因为不建议使用access_tokenquery参数。如果您无法控制此应用正在使用此令牌,请注意,由于此弃用该令牌可能会停止工作。
BogeyMan

114

Windows和所有UNIX / LINUX系统上,使用Git Bash任何其他Terminal,用YOURUSERNAME您的用户名替换并使用:

CNTX={users|orgs}; NAME={username|orgname}; PAGE=1
curl "https://api.github.com/$CNTX/$NAME/repos?page=$PAGE&per_page=100" |
  grep -e 'git_url*' |
  cut -d \" -f 4 |
  xargs -L1 git clone
  • 设置CNTX=usersNAME=yourusername,以下载所有存储库。
  • 设置CNTX=orgsNAME=yourorgname,以下载组织的所有存储库。

最大页面大小为100,因此您必须使用正确的页面编号多次调用此页面,以获取所有存储库(设置PAGE为要下载的所需页面编号)。

这是执行上述操作的Shell脚本:https : //gist.github.com/erdincay/4f1d2e092c50e78ae1ffa39d13fa404e


4
最纯的bash解决方案。仅供您参考,此bash代码几乎可以在任何* nix环境,Linux,Cygwin,Mingw中执行,当然,Gitbash与其他应用程序一样确实是终端仿真。
m3nda 2015年

1
这不适用于组织,因此无法直接回答问题。 Kenorb的这个回答确实可以处理组织,并且可以处理多达1000个回购协议-对我来说更好。
RichVel

1
带有身份验证:curl“ api.github.com/$CNTX/$NAME/… ” | grep -e'git_url *'| cut -d \“ -f 4 | xargs -L1 git clone
Yannick Wurm

2
请更新答案(2019年2月):根据GitHub API v3,您的curl应该转到/ orgs / ORGNAME / repos。也可能包括指向API v3的链接:developer.github.com/v3 另外,对于私有存储库,您需要添加curl -u“用户名”,然后curl将询问您一次密码。否则效果很好!:)))
德米特里Shevkoplyas,

1
dimitry hevkoplyas的更新评论stackoverflow.com/questions/19576742/…。尝试卷曲时,developer.github.com / v3返回301状态。使用此bash命令curl -u“ {username}”“ api.github.com/orgs {org} / repos?page = 1&per_page = 100” | grep -o'git @ [^“] *'| xargs -L1 git clone 100%
Tommy

43

组织存储库

要从您的组织克隆所有回购协议,请尝试使用以下shell一线式:

GHORG=company; curl "https://api.github.com/orgs/$GHORG/repos?per_page=1000" | grep -o 'git@[^"]*' | xargs -L1 git clone

用户存储库

使用Git存储库URL克隆所有内容:

GHUSER=CHANGEME; curl "https://api.github.com/users/$GHUSER/repos?per_page=1000" | grep -o 'git@[^"]*' | xargs -L1 git clone

使用克隆URL克隆所有文件:

GHUSER=CHANGEME; curl "https://api.github.com/users/$GHUSER/repos?per_page=1000" | grep -w clone_url | grep -o '[^"]\+://.\+.git' | xargs -L1 git clone

这是有用的shell函数,可以将其添加到用户的启动文件中(使用curl+ jq):

# Usage: gh-clone-user (user)
gh-clone-user() {
  curl -sL "https://api.github.com/users/$1/repos?per_page=1000" | jq -r '.[]|.clone_url' | xargs -L1 git clone
}

私人仓库

如果需要克隆私有存储库,则可以在标头中添加授权令牌,例如:

-H 'Authorization: token <token>'

或将其传递到参数(?access_token=TOKEN)中,例如:

curl -s "https://api.github.com/users/$GHUSER/repos?access_token=$GITHUB_API_TOKEN&per_page=1000" | grep -w clone_url | grep -o '[^"]\+://.\+.git' | xargs -L1 git clone

笔记:

  • 要仅获取私有存储库,请添加type=private到您的查询字符串中。
  • 另一种方法是hub在配置API密钥后使用。

也可以看看:


提示
-为了提高速度,请通过-Pxargs-P4= 4个进程)指定参数来设置并行进程数。
-如果您需要提高GitHub限制,请尝试通过指定API密钥进行身份验证。
-添加--recursive以递归到已注册的子模块中,并更新其中的任何嵌套子模块。


2
per_page = 1000最高时达到100
aehlke

20

该要点可以在命令行的一行中完成任务:

curl -s https://api.github.com/orgs/[your_org]/repos?per_page=200 | ruby -rubygems -e 'require "json"; JSON.load(STDIN.read).each { |repo| %x[git clone #{repo["ssh_url"]} ]}'

替换[your_org]为您的组织名称。并per_page根据需要设置。

更新:

如ATutorMe所述,根据GitHub docs,最大页面大小为100 。

如果您有超过100个存储库,则必须page在网址中添加一个参数,然后才能为每个页面运行该命令。

curl -s "https://api.github.com/orgs/[your_org]/repos?page=2&per_page=100" | ruby -rubygems -e 'require "json"; JSON.load(STDIN.read).each { |repo| %x[git clone #{repo["ssh_url"]} ]}'

注意:默认per_page参数是30


知道如何针对您可以访问的私有存储库执行此操作吗?
MichaelGofron'8

第二个不起作用,原因是“&”号使其执行后台任务
slashdottir

我在网址中添加了&access_token = <my_access_token>,效果非常好
rmartinus

第二名:page = 1(!)
Yannick Wurm,

5

转到帐户设置->应用程序并创建一个API密钥,
然后在下面的脚本中插入API密钥,github实例url和组织名称

#!/bin/bash

# Substitute variables here
ORG_NAME="<ORG NAME>"
ACCESS_TOKEN="<API KEY>"
GITHUB_INSTANCE="<GITHUB INSTANCE>

URL="https://${GITHUB_INSTANCE}/api/v3/orgs/${ORG_NAME}/repos?access_token=${ACCESS_TOKEN}"

curl ${URL} | ruby -rjson -e 'JSON.load(STDIN.read).each {|repo| %x[git clone #{repo["ssh_url"]} ]}'

将其保存在chmod u+x文件中,然后运行它。

感谢Arnaud提供了红宝石代码。


5

因此,我也将添加我的答案。:)(我发现很简单)

获取列表(我使用过“ magento”公司):

curl -si https://api.github.com/users/magento/repos | grep ssh_url | cut -d '"' -f4

使用clone_url而不是ssh_url使用HTTP访问。

因此,让我们全部克隆它们!:)

curl -si https://api.github.com/users/magento/repos | \
    grep ssh_url | cut -d '"' -f4 | xargs -i git clone {}

如果您要获取私有存储库-只需添加GET参数 ?access_token=YOURTOKEN


1
是的,没有注释需要的,只是grepping ...
萧锋锂

4

我发现提供的要点 @seancdavis中的评论非常有帮助,尤其是因为像原始海报一样,我想同步所有回购以快速访问,但是其中绝大多数是私人的。

curl -u [[USERNAME]] -s https://api.github.com/orgs/[[ORGANIZATION]]/repos?per_page=200 |
  ruby -rubygems -e 'require "json"; JSON.load(STDIN.read).each { |repo| %x[git clone #{repo["ssh_url"]} ]}'

将[[USERNAME]]替换为您的github用户名,将[[ORGANIZATION]]替换为您的Github组织。输出(JSON存储库元数据)将传递到一个简单的ruby脚本:

# bring in the Ruby json library
require "json"

# read from STDIN, parse into ruby Hash and iterate over each repo
JSON.load(STDIN.read).each do |repo|
  # run a system command (re: "%x") of the style "git clone <ssh_url>"
  %x[git clone #{repo["ssh_url"]} ]
end

1
该解决方案对我来说非常有效。实际上,我所需要做的就是将所有个人帐户存储库克隆到新的本地计算机上。设置新工作站非常方便。注意:为此,我必须更改.../orgs/[[organization]]/repos....../users/[[username]]/repos...。现在,我可以将所有工作快速导入到不同的本地计算机。谢谢!
B. Bulpett 2015年


2

这个python一线客可满足您的需求。它:

  • 检查github是否有可用的存储库
  • 对于每个,进行系统调用 git clone

    python -c "import json, urllib, os; [os.system('git clone ' + r['ssh_url']) for r in json.load(urllib.urlopen('https://api.github.com/orgs/<<ORG_NAME>>/repos?per_page=200'))]"
    

2
curl -s https://api.github.com/orgs/[GITHUBORG_NAME]/repos | grep clone_url | awk -F '":' '{ print $2 }' | sed 's/\"//g' | sed 's/,//' | while read line; do git clone "$line"; done

2
请为您的解决方案添加说明。这样,其他存在类似问题的人将能够更轻松地理解您的解决方案!
Nander Speerstra

一个细节是需要通过页码的?page=2
Bruno Wego

2

简单的解决方案:

NUM_REPOS=1000
DW_FOLDER="Github_${NUM_REPOS}_repos"
mkdir ${DW_FOLDER}
cd ${DW_FOLDER}
for REPO in $(curl https://api.github.com/users/${GITHUB_USER}/repos?per_page=${NUM_REPOS} | awk '/ssh_url/{print $2}' | sed 's/^"//g' | sed 's/",$//g') ; do git clone ${REPO} ; done

2

我尝试了上面的一些命令和工具,但认为它们太麻烦了,因此我编写了另一个命令行工具来执行此操作,称为github-dl

要使用它(假设您已经安装了nodejs)

npx github-dl -d /tmp/test wires

这将使用您在CLI上提供的授权详细信息(用户/密码)从中获取所有存储库的列表wires并将信息写入test目录。

详细来说

  1. 要求身份验证(支持2FA)
  2. 通过Github API获取用户/组织的仓库清单
  3. 是否为此进行分页,因此支持100多个repo

它实际上并没有克隆存储库,而是编写了一个.txt您可以传递xargs来进行克隆的文件,例如:

cd /tmp/test
cat wires-repo-urls.txt | xargs -n2 git clone

# or to pull
cat /tmp/test/wires-repo-urls.txt | xargs -n2 git pull

也许这对您有用;只是几行JS,所以应该很容易适应您的需求


1

还有一个非常有用的npm模块可以执行此操作。它不仅可以克隆,还可以拉(以更新您已经拥有的数据)。

您只需像这样创建配置:

[{
   "username": "BoyCook",
   "dir": "/Users/boycook/code/boycook",
   "protocol": "ssh"
}]

gitall clone例如。要么gitall pull


1

如果有人在寻找Windows解决方案,则可以使用PowerShell中的一个小功能来解决问题(如果不是事实,我需要它可以与代理一起使用,也可以与代理一起使用,可以是oneliner / alias)。

function Unj-GitCloneAllBy($User, $Proxy = $null) {
    (curl -Proxy $Proxy "https://api.github.com/users/$User/repos?page=1&per_page=100").Content 
      | ConvertFrom-Json 
      | %{ $_.clone_url } 
      # workaround git printing to stderr by @wekempf aka William Kempf
      # https://github.com/dahlbyk/posh-git/issues/109#issuecomment-21638678
      | %{ & git clone $_ 2>&1 } 
      | % { $_.ToString() }
}

1

因此,在实践中,如果您想从组织中克隆所有FOO匹配的仓库,则BAR可以使用下面的一列式,这需要jq和通用的cli实用程序

curl 'https://api.github.com/orgs/FOO/repos?access_token=SECRET' |
  jq '.[] |
  .ssh_url' |
  awk '/BAR/ {print "git clone " $0 " & "}' |
  sh

1

另一个带有注释的shell脚本,可从用户克隆所有存储库(公共和私有):

#!/bin/bash

USERNAME=INSERT_USERNAME_HERE
PASSWORD=INSERT_PASSWORD_HERE

# Generate auth header
AUTH=$(echo -n $USERNAME:$PASSWORD | base64)

# Get repository URLs
curl -iH "Authorization: Basic "$AUTH https://api.github.com/user/repos | grep -w clone_url > repos.txt

# Clean URLs (remove " and ,) and print only the second column
cat repos.txt | tr -d \"\, | awk '{print $2}'  > repos_clean.txt

# Insert username:password after protocol:// to generate clone URLs
cat repos_clean.txt |  sed "s/:\/\/git/:\/\/$USERNAME\:$PASSWORD\@git/g" > repos_clone.txt

while read FILE; do
    git clone $FILE
done <repos_clone.txt

rm repos.txt & rm repos_clone.txt

1

在您的网站中创建一个bash别名/功能 ~/.bashrc file

我通过在我的别名中创建别名/ bash函数来为团队解决了这个问题 ~/.bashrc file

脚步

打开终端或linux shell并打开您的~/.bashrc file

sudo nano ~/.bashrc

添加此功能:

CloneAll() {
    # Make the url to the input github organization's repository page.
    ORG_URL="https://api.github.com/orgs/${1}/repos?per_page=200";

    # List of all repositories of that organization (seperated by newline-eol).
    ALL_REPOS=$(curl -s ${ORG_URL} | grep html_url | awk 'NR%2 == 0' \
                | cut -d ':' -f 2-3 | tr -d '",');

    # Clone all the repositories.
    for ORG_REPO in ${ALL_REPOS}; do
        git clone ${ORG_REPO}.git;
    done
}

保存并关闭〜/ .bashrc文件,然后关闭终端-您需要执行此操作,否则新的func将不会初始化:

打开新的终端并尝试一下:

CloneAll <your_github_org_name>

:如果您的个人github回购URL被称为https://github.com/awesome-async,则命令为

CloneAll awesome-async

重要

per_page=200在第一变量的末尾ORG_URL设置将克隆回购的数量,所以要特别注意那些:

ORG_URL="https://api.github.com/orgs/${1}/repos?per_page=200";  <---- make sure this is what you want

希望这可以帮助!:)


似乎最大 per_page的值为100 ...对于大型组织,添加页码作为第二个参数,它非常适合我的需要...repos?page=${2}&per_page=100";
sv3n

0

您可以使用来获取存储库列表,curl然后使用bash循环遍历该列表:

GIT_REPOS=`curl -s curl https://${GITHUB_BASE_URL}/api/v3/orgs/${ORG_NAME}/repos?access_token=${ACCESS_TOKEN} | grep ssh_url | awk -F': ' '{print $2}' | sed -e 's/",//g' | sed -e 's/"//g'`
for REPO in $GIT_REPOS; do
  git clone $REPO
done


0

要仅克隆私有存储库,给定访问密钥,给定python 3和请求模块,请执行以下操作:

ORG=company; ACCESS_KEY=0000000000000000000000000000000000000000; for i in $(python -c "import requests; print(' '.join([x['ssh_url'] for x in list(filter(lambda x: x['private'] ,requests.get('https://api.github.com/orgs/$ORG/repos?per_page=1000&access_token=$ACCESS_KEY').json()))]))"); do git clone $i; done;

0

一个Python3解决方案,其中包括通过LinkHeader进行详尽的分页。

先决条件:


import json
import requests
from requests.auth import HTTPBasicAuth
import links_from_header

respget = lambda url: requests.get(url, auth=HTTPBasicAuth('githubusername', 'githubtoken'))

myorgname = 'abc'
nexturl = f"https://api.github.com/orgs/{myorgname}/repos?per_page=100"

while nexturl:
    print(nexturl)
    resp = respget(nexturl)

    linkheads = resp.headers.get('Link', None)
    if linkheads:
        linkheads_parsed = links_from_header.extract(linkheads)
        nexturl = linkheads_parsed.get('next', None)
    else:
        nexturl = None

    respcon = json.loads(resp.content)
    with open('repolist', 'a') as fh:
        fh.writelines([f'{respconi["full_name"]}\n' for respconi in respcon])

然后,您可以使用xargs并行和:cat repolist | parallel -I% hub clone %


0

如果您在这样的列表中有存储库列表,则此shell脚本有效:

user="https://github.com/user/"

declare -a arr=("repo1", "repo2")

for i in "${arr[@]}"

do

   echo $user"$i"

   git clone $user"$i"

done 

如果有一些私有存储库,则可以通过以下方式更新“用户”:user =“ user:password@github.com/user
Med Ali Difallah

0

我创建了一个示例批处理脚本。您可以从github.com下载所有私有/公共存储库。下载存储库后,它将自动转换为zip文件。

@echo off
setlocal EnableDelayedExpansion
SET "username=olyanren"
SET "password=G....."
set "mypath=%cd%\"
SET "url=https://%username%:%password%@github.com/%username%/"
FOR /F "tokens=* delims=" %%i in (files.txt) do (
SET repo=%%i
rmdir /s /q !repo!
git clone "!url!!repo!.git"
cd !repo!
echo !mypath!
git archive --format=zip -o "!mypath!!repo!.zip" HEAD
cd ..
)

注意:files.txt文件应仅包含存储库名称,例如:

repository1
repository2

0

5月19日更新

对组织使用此bash命令(包括私人仓库)

curl -u "{username}" "https://api.github.com/orgs/{org}/repos?page=1&per_page=100" | grep -o 'git@[^"]*' | xargs -L1 git clone

0

尽管您可以在其中指定什么,但此处的主流答案并未考虑到Github API最多只会返回100个存储库。 per_page。如果要克隆的Github组织包含超过100个存储库,则必须遵循API响应中的分页链接。

我写了一个CLI工具来做到这一点

clone-github-org -o myorg

这会将myorg组织中的所有存储库克隆到当前工作目录。


0

对于组织,您可以使用私有存储库访问:

curl -u <YOUR_GITHUB_USERNAME> -s https://api.github.com/orgs/<ORG_NAME>/repos?per_page=200 | ruby -rubygems -e ’require “json”; JSON.load(STDIN.read).each { |repo| %x[git clone #{repo[“html_url”]} ]}'

它使用html_url,因此您不需要access_token在提示时输入github密码。


不建议使用使用API​​密码的基本身份验证,并且很快将不再起作用。访问[deprecating-password-auth](developer.github.com/changes/…),以获取有关建议的解决方法和删除日期的更多信息。
BogeyMan

@BogeyMan感谢您的更新!
Flavio

0

克隆所有非fork的仓库:

curl -u "username" https://api.github.com/user/repos\?page\=1\&per_page\=100 |
  jq -r 'map(select(.fork == false)) | .[] | .ssh_url' |
  xargs -L1 git clone

克隆要点:

curl https://api.github.com/users/username/gists\?page\=1\&per_page\=100 |
   jq -r ".[] | .git_pull_url +\" '\" + (.files|keys|join(\"__\") + \"'\")" |
   xargs -L1 git clone

jq命令很复杂,因为要点的存储库名称是散列,因此该命令将所有文件名连接为存储库名称


您可以使用任意过滤JSON jq

安装: sudo apt-get install jq

在上面的示例中,我使用以下方法滤除了分叉curl ... | jq -r 'map(select(.fork == false))' ...- 对于不克隆发出临时请求请求的存储库很有用

jq支持一些非常高级的功能。man jq是你的朋友


您可以通过身份验证curl -u "username" ... 访问私有存储库


Guthub的API网址

  • 您的存储库(需要身份验证): https://api.github.com/user/repos\?page\=1\&per_page\=100
  • 任何用户: https://api.github.com/users/other_username/repos\?page\=1\&per_page\=100
  • 单位: https://api.github.com/orgs/orgname/repos\?page\=1\&per_page\=100

Github API文档用于仓库


0
"""
Clone all public Github Repos

https://developer.github.com/v3/repos/#list-repositories-for-a-user
"""

import urllib.request, base64
import json
import os


def get_urls(username):
    url = f"https://api.github.com/users/{username}/repos?per_page=200"
    request = urllib.request.Request(url)
    result = urllib.request.urlopen(request)
    return json.load(result)


if __name__ == "__main__":
    for r in get_urls("MartinThoma"):
        if not os.path.isdir(r["name"]):
            print(f"Clone {r['name']}...")
            os.system("git clone " + r["ssh_url"])
        else:
            print(f"SKIP {r['name']}...")

0

要克隆所有自己的私有和公共存储库,只需生成一个具有存储库访问权限的新访问令牌,并使用此令牌:

(替换为您自己的访问令牌和用户名)

for line in $(curl https://api.github.com/user/repos?access_token=ACCESS_TOKEN_HERE  | grep -o "git@github.com:YOUR_USER_NAME/[^ ,\"]\+");do git clone $line;done

这将克隆当前文件夹中的所有存储库

这是一个小小的bash程序,您可以将其粘贴到终端中,然后按Enter

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.