Como clonar todos os repositórios de uma vez no GitHub?


97

Tenho uma conta corporativa no GitHub e quero fazer backup de todos os repositórios contidos, levando em consideração qualquer coisa nova que possa ser criada para fins de automação. Eu esperava algo assim:

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

ou algo semelhante funcionaria, mas não parece gostar do curinga aqui.

Existe uma maneira no Git de clonar e extrair tudo, assumindo que alguém tenha as permissões apropriadas?


2
Boa pergunta. E que tal mantê-los sincronizados, via pull? Alguma das respostas funciona para puxões?
nealmcb

Precisamos de uma solução python, para aqueles de nós não tão adeptos de node ou ruby;) Ou o github deve ler isso e ter pena de nós e apenas fornecer uma interface web simples para isso ....
nealmcb

Respostas:


52

Não acho que seja possível fazer dessa forma. Sua melhor aposta é encontrar e percorrer uma lista de repositórios de uma organização usando a API.

Experimente isto:

  • Crie um token de API acessando Configurações da conta -> Aplicativos
  • Faça uma chamada para: http://${GITHUB_BASE_URL}/api/v3/orgs/${ORG_NAME}/repos?access_token=${ACCESS_TOKEN}
  • A resposta será uma matriz JSON de objetos. Cada objeto incluirá informações sobre um dos repositórios dessa Organização. Acho que, no seu caso, você estará procurando especificamente pela ssh_urlpropriedade.
  • Em seguida, git clonecada um desses ssh_urls.

É um pouco de trabalho extra, mas é necessário que o GitHub tenha a autenticação adequada.


Eu criei o token de API e estou recebendo a saída da chamada, mas não vejo nada que faça referência ao que sei sobre nossos repositórios ou a string 'ssh_url'. Suspeito que não fiz a ligação corretamente. curl -i https://github.com/api/v3/orgs/company/repos?access_token=<token>
numb3rs1x

É uma conta GitHub Enterprise ou github.com?
Thomas Kelley

1
Ah, eu não entendi você. Achei que fosse uma conta Enterprise. Em vez de https://github.com/api/v3/, tente https://api.github.com/.
Thomas Kelley

1
E não tenho certeza de como sua empresa em particular está configurada, mas se for um "usuário" em vez de uma "organização", você deverá usar o /users/${COMPANY}/reposcaminho em vez de /orgs/${COMPANY}/repos.
Thomas Kelley

1
Por GitHub: use o cabeçalho HTTP de autorização, pois o uso do access_tokenparâmetro de consulta está obsoleto. Se este token estiver sendo usado por um aplicativo sobre o qual você não tem controle, esteja ciente de que ele pode parar de funcionar como resultado desta suspensão de uso.
BogeyMan

114

No Windows e em todos os sistemas UNIX / LINUX , usando Git Bash ou qualquer outro Terminal , substitua YOURUSERNAMEpelo seu nome de usuário e use:

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
  • Defina CNTX=userse NAME=yourusername, para baixar todos os seus repositórios.
  • Configure CNTX=orgse NAME=yourorgname, para baixar todos os repositórios de sua organização.

O tamanho máximo da página é 100, então você tem que chamar isso várias vezes com o número da página correto para obter todos os seus repositórios (defina PAGEo número da página desejada que deseja baixar).

Aqui está um script de shell que faz o acima: https://gist.github.com/erdincay/4f1d2e092c50e78ae1ffa39d13fa404e


4
Solução bash pura, a mais simples. Para sua informação, este código bash pode ser executado em quase qualquer ambiente * nix, Linux, Cygwin, Mingw e, claro, o Gitbash que é realmente uma emulação de terminal como os outros.
m3nda

1
Isso não funciona com organizações, portanto, não responde diretamente à pergunta. Esta resposta do Kenorb lida com organizações e funciona para até 1000 repositórios também - funcionou melhor para mim.
RichVel

1
com autenticação: curl " api.github.com/$CNTX/$NAME/… " | grep -e 'git_url *' | cut -d \ "-f 4 | xargs -L1 clone git
Yannick Wurm

2
Atualize a resposta (fevereiro de 2019): de acordo com a API do GitHub v3, seu curl deve ir para / orgs / ORGNAME / repos. Também pode incluir um link para a API v3: developer.github.com/v3 Também para repositórios privados, você precisaria adicionar curl -u "nome de usuário", então curl pedirá a sua senha uma vez. Caso contrário, está funcionando muito bem!
:)

1
ATUALIZAÇÃO de dimitry hevkoplyas comentário stackoverflow.com/questions/19576742/… . developer.github.com/v3 retorna o status 301 quando tenta enrolar. use este comando bash curl -u "{username}" " api.github.com/orgs {org} / repos? page = 1 & per_page = 100" | grep -o 'git @ [^ "] *' | xargs -L1 clone git funciona 100%
Tommy

43

Repositórios de organização

Para clonar todos os repos de sua organização, tente o seguinte shell one-liner:

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

Repositórios de usuário

Clonando tudo usando URLs de repositório Git:

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

Clonando tudo usando 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

Aqui está a função shell útil que pode ser adicionada aos arquivos de inicialização do usuário (usando 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
}

Repositórios privados

Se precisar clonar os repositórios privados, você pode adicionar token de autorização em seu cabeçalho, como:

-H 'Authorization: token <token>'

ou passe-o no parâmetro ( ?access_token=TOKEN), por exemplo:

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

Notas:

  • Para buscar apenas repositórios privados, adicione type=privateem sua string de consulta.
  • Outra maneira é usar hubdepois de configurar sua chave API.

Veja também:


Dicas :
- Para aumentar a velocidade, defina o número de processos paralelos especificando o -Pparâmetro para xargs( -P4= 4 processos).
- Se você precisar aumentar os limites do GitHub, tente autenticar especificando sua chave de API.
- Adicionar --recursivepara recursar nos submódulos registrados e atualizar quaisquer submódulos aninhados dentro deles.


2
per_page = 1000 máximas às 100
aehlke

20

Esta essência realiza a tarefa em uma linha na linha de comando:

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

Substitua [your_org]pelo nome da sua organização. E defina o seu, per_pagese necessário.

ATUALIZAR:

Como o ATutorMe mencionou, o tamanho máximo da página é 100, de acordo com a documentação do GitHub .

Se você tiver mais de 100 repositórios, terá que adicionar um pageparâmetro ao seu url e poderá executar o comando para cada página.

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

Nota: o per_pageparâmetro padrão é 30.


Alguma ideia de como isso é feito para repositórios privados aos quais você tem acesso?
MichaelGofron

o segundo não funciona porque o e comercial faz com que vá para uma tarefa em segundo plano
slashdottir

Eu adicionei & access_token = <my_access_token> ao url e funcionou perfeitamente
rmartinus

2º um: página = 1 (!)
Yannick Wurm

5

Vá para Configurações da conta -> Aplicativo e crie uma chave de API
Em seguida, insira a chave de API, o URL da instância do github e o nome da organização no script abaixo

#!/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"]} ]}'

Salve isso em um arquivo, chmod u+xo arquivo, e execute-o.

Agradecimentos a Arnaud pelo código ruby.


5

Então, vou adicionar minha resposta também. :) (descobri que é simples)

Buscar lista (usei a empresa "magento"):

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

Use em clone_urlvez disso ssh_urlpara usar o acesso HTTP.

Então, vamos clonar todos eles! :)

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

Se você for buscar repositórios privados - basta adicionar o parâmetro GET ?access_token=YOURTOKEN


1
Sim, nenhum rubi necessário, apenas grepping ...
Xiao-Feng Li

4

Achei um comentário na essência do @seancdavis fornecido para ser muito útil, especialmente porque, como o autor do pôster original, eu queria sincronizar todos os repositórios para acesso rápido, porém a grande maioria deles eram privados.

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

Substitua [[NOME DE USUÁRIO]] pelo nome de usuário do github e [[ORGANIZAÇÃO]] pela organização do Github. A saída (metadados do repositório JSON) será passada para um script ruby ​​simples:

# 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
Esta solução funcionou perfeitamente para mim. Na verdade, tudo que eu precisava era clonar todos os meus repositórios de conta pessoal para minha nova máquina local. Muito útil para configurar uma nova estação de trabalho. Nota: para fazer isso, tive que mudar .../orgs/[[organization]]/repos...para .../users/[[username]]/repos.... Agora posso importar rapidamente todo o meu trabalho para diferentes máquinas locais. OBRIGADO!
B. Bulpett


2

Este one-liner do python fará o que você precisa. Isto:

  • verifica o github para seus repositórios disponíveis
  • para cada um, faz uma chamada de sistema para 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
Adicione uma explicação à sua solução. Dessa forma, outras pessoas com problemas semelhantes poderão entender sua solução mais facilmente!
Nander Speerstra

Um detalhe é o número da página necessária para passar como ?page=2.
Bruno Wego

2

Solução simples:

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

Tentei alguns dos comandos e ferramentas acima, mas decidi que eles eram muito complicados, então escrevi outra ferramenta de linha de comando para fazer isso, chamada github-dl.

Para usá-lo (supondo que você tenha nodejs instalado)

npx github-dl -d /tmp/test wires

Isso obteria uma lista de todos os repositórios de wirese as informações de gravação no testdiretório, usando os detalhes de autorização (usuário / senha) que você fornecer na CLI.

Em detalhes,

  1. Pede autenticação (suporta 2FA)
  2. Obtém uma lista de repositórios para usuário / organização por meio da API do Github
  3. Faz paginação para isso, então mais de 100 repositórios são suportados

Na verdade, ele não clona os repositórios, mas, em vez disso, grava um .txtarquivo que você pode usar xargspara fazer a clonagem, por exemplo:

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

Talvez isso seja útil para você; são apenas algumas linhas de JS, então deve ser fácil de ajustar às suas necessidades


1

Também existe um módulo npm muito útil para fazer isso. Ele pode não apenas clonar, mas também extrair (para atualizar os dados que você já possui).

Você acabou de criar uma configuração como esta:

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

e fazer gitall clonepor exemplo. Ougitall pull


1

Caso alguém procure uma solução Windows, aqui está uma pequena função no PowerShell para fazer o truque (poderia ser uma linha / alias, se não o fato de que preciso que funcione com e sem proxy).

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

Então, na prática, se você quiser clonar todos os repos da organização FOOque correspondem BAR, você pode usar o one-liner abaixo, que requer utilitários jq e cli comuns

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

1

Outro script de shell com comentários que clona todos os repositórios (públicos e privados) de um usuário:

#!/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

Crie um alias / função bash em seu ~/.bashrc file

Resolvi isso para minha equipe criando uma função alias / bash em meu ~/.bashrc file

passos

abra um terminal ou shell do Linux e abra o seu ~/.bashrc file:

sudo nano ~/.bashrc

adicione esta função:

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
}

salve e feche seu arquivo ~ / .bashrc e feche o terminal - você precisa fazer isso ou a nova função não inicializará:

abra um novo terminal e experimente:

CloneAll <your_github_org_name>

exemplo : se o seu URL de repositório github pessoal se chama https://github.com/awesome-async, o comando seria

CloneAll awesome-async

Importante

o per_page=200no final da primeira variável ORG_URLdefine o número de repositórios que serão clonados, então preste atenção especial a isso:

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

Espero que isto ajude! :)


Parece max. o valor para per_page é 100 ... para organizações grandes adicionou o número da página como segundo parâmetro e funciona perfeitamente para minhas necessidades...repos?page=${2}&per_page=100";
sv3n

0

Você pode obter uma lista dos repositórios usando curle, em seguida, iterar sobre essa lista com um loop 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

Para clonar apenas repositórios privados, dada uma chave de acesso, e dado python 3 e módulo de solicitações instalado:

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

Uma solução Python3 que inclui paginação exaustiva por meio do Linkcabeçalho.

Pré-requisitos:


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])

Então, você pode usar xargsou paralelo e:cat repolist | parallel -I% hub clone %


0

Se você tiver uma lista de repositórios em uma lista como esta, este script de shell funcionará:

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

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

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

do

   echo $user"$i"

   git clone $user"$i"

done 

se houver alguns repositórios privados, você pode atualizar "usuário" desta forma: user = " usuário:
senha@github.com/user

0

Criei um script de lote de amostra. Você pode baixar todos os repositórios privados / públicos em github.com. Depois que um repositório é baixado, ele é automaticamente convertido em um arquivo 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 ..
)

Observação: o arquivo files.txt deve conter apenas nomes de repositórios como:

repository1
repository2

0

Atualização de 19 de maio

use este comando bash para uma organização (repo privado incluído)

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

0

As respostas predominantes aqui não levam em consideração que a API do Github retornará apenas um máximo de 100 repositórios, apesar do que você pode especificar em per_page. Se você estiver clonando uma Github org com mais de 100 repositórios, terá que seguir os links de paginação na resposta da API.

Eu escrevi uma ferramenta CLI para fazer exatamente isso :

clone-github-org -o myorg

Isso clonará todos os repositórios da myorgorganização para o diretório de trabalho atual.


0

Para organizações às quais você tem acesso com repositórios privados:

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

Ele usa o html_url, então você não precisa access_tokenapenas inserir sua senha do github quando solicitado.


A autenticação básica usando uma senha para a API está obsoleta e em breve não funcionará mais. Visite [deprecating-password-auth] ( developer.github.com/changes/… ) para obter mais informações sobre soluções alternativas e datas de remoção sugeridas.
BogeyMan

@BogeyMan obrigado pela atualização!
Flavio

0

Clone todos os seus repos que não sejam bifurcações:

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

Clone seus pontos essenciais:

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

Este jqcomando é complexo porque os nomes do repo de gists são hashes, de modo que o comando concatena todos os nomes de arquivos para serem o nome do repo


Você pode filtrar o JSON arbitrariamente usando jq

instalar: sudo apt-get install jq

No exemplo acima, eu filtrei garfos usando isto: curl ... | jq -r 'map(select(.fork == false))' ...- útil para não clonar repositórios onde você fez solicitações de pull casuais

jq oferece suporte a alguns recursos muito avançados. man jqé seu amigo


Você pode autenticar com curl -u "username" ... para acessar repositórios privados


URLs da API do Guthub

  • Seus repos (precisa de autenticação): https://api.github.com/user/repos\?page\=1\&per_page\=100
  • Qualquer usuário: https://api.github.com/users/other_username/repos\?page\=1\&per_page\=100
  • Orgs: https://api.github.com/orgs/orgname/repos\?page\=1\&per_page\=100

Github API Docs para repositórios


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

Para clonar todos os seus próprios repositórios públicos e privados, gere um novo token de acesso com acesso aos repositórios e use:

(substitua por seu próprio token de acesso e nome de usuário)

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

Isto irá clonar todos os repositórios da pasta atual

Este é um pequeno programa bash, você pode simplesmente colá-lo no terminal e pressionar Enter

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.