224

I have a company GitHub account and I want to back up all of the repositories within, accounting for anything new that might get created for purposes of automation. I was hoping something like this:

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

or similar would work, but it doesn't seem to like the wildcard there.

Is there a way in Git to clone and then pull everything assuming one has the appropriate permissions?

kenorb
  • 155,785
  • 88
  • 678
  • 743
numb3rs1x
  • 4,673
  • 5
  • 31
  • 44
  • 5
    Good question. And how about keeping them in sync, via pull? Do any of the answers work for pulls? – nealmcb May 17 '15 at 17:37
  • 1
    We need a python solution, for those of us not so adept at node or ruby ;) Or github should read this and take pity on us and just provide a simple web interface for this.... – nealmcb May 18 '15 at 03:33
  • 1
    Try: https://github.com/wballard/git-friends – kenorb Sep 26 '15 at 22:59
  • You can use [ghorg](https://github.com/gabrie30/ghorg) then just `ghorg clone org --backup --clone-wiki --token=xxxx` – jimjam Nov 10 '21 at 16:02
  • To keep repos in sync, see [this answer](https://stackoverflow.com/a/68770988/992887) which includes this - there may be others – RichVel Nov 18 '22 at 18:08

46 Answers46

202

Simple script using GitHub CLI (no API keys)

Here's a simple solution using the official GitHub CLI tool, gh - no need for API keys and can handle up to 1000 private repos.

First time only: login with gh for private repos, and follow prompts:

gh auth login

Now you can clone any number of repos under a new ./myorgname folder. Replace myorgname with your org name:

gh repo list myorgname --limit 1000 | while read -r repo _; do
  gh repo clone "$repo" "$repo"
done

This should work on Mac or Linux.

On Windows?

  • Run this script in WSL or Git Bash, part of Git for Windows
  • Or try comment here by @Karson for similar script in PowerShell

Setup

To get the GitHub CLI tool:

Future proofing: the GitHub CLI tool will be supported long-term as and when the GitHub API changes. Some older answers here don't work any more due to this.

Optional: update existing checkouts

To update repo folders already on disk, as well as cloning new repos, the script needs to check for failure of the gh repo clone, like this:

gh repo list myorgname --limit 1000 | while read -r repo _; do
  gh repo clone "$repo" "$repo" -- -q 2>/dev/null || (
    cd "$repo"
    # Handle case where local checkout is on a non-main/master branch
    # - ignore checkout errors because some repos may have zero commits, 
    # so no main or master
    git checkout -q main 2>/dev/null || true
    git checkout -q master 2>/dev/null || true
    git pull -q
  )
done

Tips

  • Don't want to create repos in the ./myorgname folder? Drop the second "$repo" argument to gh repo clone to create them in current directory

To filter results:

  • --no-archived - omit archived repositories
  • --source - show only non-forks

More than 1000 repos?

This script handles at most 1000 repos, because gh uses GitHub Search API, which returns up to 1000 results per query.

To work around this limit:

  • make sure you are omitting archived and forked repos
  • see gh repo list --help for filtering by language, topic, etc
  • use a different answer based on API requests that replaces this script, or just the gh repo list command

Background

RichVel
  • 7,030
  • 6
  • 32
  • 48
  • 12
    A great solution IMO. I spent the better part of the morning doing exactly this (writing a solution using `gh`) because I failed to go to the second page of answers. I hope this gets upvoted so that others don't repeat the same mistake. – Pranasas Sep 10 '21 at 13:19
  • 6
    By far, the easiest solution to implement. – Ketouem Nov 22 '21 at 10:38
  • Here's a [Python3 implementation](https://gist.github.com/jon-eric/a746be60c28730044ef3049fbdbdf6b1) of this approach using `gh`. – Jon-Eric Jun 02 '22 at 19:14
  • 4
    This solution is really clean. I wonder if pulling down all remote branches for each repo can be achieved easily as well. – Taylor D. Edmiston Jun 15 '22 at 23:58
  • 1
    If you're on Windows wondering how you're supposed to run this... (1) Right click inside the folder you want all of the repos to clone to (2) select "Git Bash Here" - Bash window will open (3) Edit the script with your org name, then copy and paste it into the bash window (maybe make sure line endings are unix based, not sure, I did just to be safe). (4) it should start running. – Taylor Brown Jun 17 '22 at 19:48
  • 2
    @TaylorD.Edmiston See [this answer](https://stackoverflow.com/questions/67699/how-do-i-clone-all-remote-branches) for ways to clone all branches, and use `git branch -a` to see them. The normal `git clone` does include the remote tracking branches. You could add commands after the main script's `gh repo clone`, something like this: `( cd "$repo" && COMMANDS_HERE )` - the parens create a subshell to limit scope of `cd`. Take care with `git push` - by default it will push all branches: [comment](https://stackoverflow.com/questions/67699/how-do-i-clone-all-remote-branches#comment975098_72156) – RichVel Jul 14 '22 at 07:24
  • Are there good ways to take these and create new repos, say in another github instance / organization? – VictorLegros Sep 15 '22 at 04:27
  • 1
    @VictorLegros - best if you ask a new question about that, maybe with a link to this question if context is helpful. Your question is really how to migrate/copy repos to another GitHub instance/organisation, and this may already be answered. – RichVel Sep 15 '22 at 08:56
  • how to fix 'while' is not recognized as an internal or external command, operable program or batch file. issue? – joantoh Apr 02 '23 at 15:57
  • 1
    @joantoh you seem to be running this bash script from a Windows command prompt / terminal which expects batch files or PowerShell. See the part of the answer that talks about 'On Windows?', and run the script within Git Bash – RichVel Apr 04 '23 at 15:12
  • 1
    PowerShell version [here](https://gist.github.com/KarsonAlford/f26f1bcca772d9ac6a76d8594155f923#file-clone-all-repos) – Karson Aug 09 '23 at 18:04
  • @Karson nice script, mentioned your comment in answer – RichVel Aug 16 '23 at 08:48
188

On Windows and all UNIX/LINUX systems, using Git Bash or any other Terminal, replace your USERNAME by your username and use:

CNTX={users|orgs}; NAME={username|orgname}; PAGE=1
curl "https://api.github.com/$CNTX/$NAME/repos?page=$PAGE&per_page=100" |
  grep -e 'clone_url*' |
  cut -d \" -f 4 |
  xargs -L1 git clone
  • Set CNTX=users and NAME=yourusername, to download all your repositories.
  • Set CNTX=orgs and NAME=yourorgname, to download all repositories of your organization.

The maximum page-size is 100, so you have to call this several times with the right page number to get all your repositories (set PAGE to the desired page number you want to download).

Here is a shell script that does the above: https://gist.github.com/erdincay/4f1d2e092c50e78ae1ffa39d13fa404e

Erdinc Ay
  • 3,224
  • 4
  • 27
  • 42
  • 7
    Pure bash solution, the most simplest. For your information, this bash code can be executed in almost any *nix enviroment, Linux, Cygwin, Mingw and of course the Gitbash wich is really a terminal emulation like others. – m3nda Oct 05 '15 at 11:32
  • 2
    This doesn't work with organizations, so it doesn't directly answer the question. [This answer](https://stackoverflow.com/a/32803025/992887) from Kenorb does handle orgs and works for up to 1000 repos as well - worked better for me. – RichVel Jan 26 '18 at 07:39
  • 1
    how do u use this for private repos of the org – timberlake Mar 09 '18 at 17:46
  • 3
    with authentification: curl "https://api.github.com/$CNTX/$NAME/repos?page=$PAGE&per_page=100&access_token=$ACCESS_TOKEN" | grep -e 'git_url*' | cut -d \" -f 4 | xargs -L1 git clone – Yannick Wurm Mar 19 '18 at 22:37
  • 5
    Please update answer (Feb-2019): according to GitHub API v3 your curl should go to /orgs/ORGNAME/repos. Also maybe include a link to API v3: https://developer.github.com/v3/ Also for private repos you would need to add curl -u "username", then curl will ask you password once. Otherwise working great! : ))) – Dmitry Shevkoplyas Feb 15 '19 at 21:00
  • 1
    working sample CNTX={orgs}; NAME={officedev}; 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 – Ved Prakash Mar 18 '19 at 06:20
  • 3
    UPDATE from dimitry hevkoplyas comment https://stackoverflow.com/questions/19576742/how-to-clone-all-repos-at-once-from-github#comment96219716_32833411. developer.github.com/v3 returns 301 status when try to curl. use this bash command curl -u "{username}" "https://api.github.com/orgs/{org}/repos?page=1&per_page=100" | grep -o 'git@[^"]*' | xargs -L1 git clone works 100% – Tommy May 04 '19 at 09:01
  • 3
    This only grabs the public repos, not the private and internal ones. – wogsland Feb 05 '20 at 12:18
  • 2
    Does this only download public repositories, or private ones too? – stevec Aug 16 '20 at 20:00
  • 1
    The simplicity of this answer is nice, but the answer using GitHub's CLI `gh` is even simpler. https://stackoverflow.com/a/68770988/149428 – Taylor D. Edmiston Jun 15 '22 at 23:52
  • @user:149428 I was the reason why they created **gh-cli** : )) – Erdinc Ay Feb 16 '23 at 12:21
  • Could you please explain what should be changed here? YOURUSERNAME does not appear in your code snippet. – Robbie Mallett Mar 10 '23 at 09:35
  • thank you Robbie, I corrected the snippet – Erdinc Ay Mar 12 '23 at 17:45
73

I don't think it's possible to do it that way. Your best bet is to find and loop through a list of an Organization's repositories using the API.

Try this:

  • Create an API token by going to Account Settings -> Applications
  • Make a call to: http://${GITHUB_BASE_URL}/api/v3/orgs/${ORG_NAME}/repos?access_token=${ACCESS_TOKEN}
  • The response will be a JSON array of objects. Each object will include information about one of the repositories under that Organization. I think in your case, you'll be looking specifically for the ssh_url property.
  • Then git clone each of those ssh_urls.

It's a little bit of extra work, but it's necessary for GitHub to have proper authentication.

Thomas Kelley
  • 10,187
  • 1
  • 36
  • 43
  • 1
    I created the API token and I'm getting output from the call, but I do not see anything referencing what I know of our repositories or the 'ssh_url' string. I suspect I didn't do the call properly. `curl -i https://github.com/api/v3/orgs/company/repos?access_token=` – numb3rs1x Oct 24 '13 at 21:59
  • 1
    Is this a GitHub Enterprise account, or github.com? – Thomas Kelley Oct 24 '13 at 22:05
  • 2
    Ah, I misunderstood you. I thought it was en Enterprise account. Instead of `https://github.com/api/v3/`, try `https://api.github.com/`. – Thomas Kelley Oct 24 '13 at 22:08
  • 2
    And I'm not sure how your particular company is set up, but if it's a "user" instead of an "organization", then you'll want to use the `/users/${COMPANY}/repos` path instead of `/orgs/${COMPANY}/repos`. – Thomas Kelley Oct 24 '13 at 22:10
  • 1
    You might find this link helpful... It has all the current API paths: http://developer.github.com/v3/ – Thomas Kelley Oct 24 '13 at 22:11
  • 1
    I found what I think is the right call, but I'm not getting all the repos that I can see when I bring up the organization in the browser. This is what I found show some of them: `https://api.github.com/orgs/company/repos?access_token=` – numb3rs1x Oct 25 '13 at 05:04
  • 1
    see my comment below and use whenever you want http://stackoverflow.com/a/32932865/3022613 – muhasturk Oct 04 '15 at 11:20
  • 1
    my jutils command line client supports this: https://github.com/jjYBdx4IL/misc/tree/master/jutils – user1050755 Jun 27 '17 at 21:11
  • 2
    if you prefer using a cli [ghorg](https://github.com/gabrie30/ghorg) will accomplish this task for you – jimjam Jun 16 '19 at 18:26
  • 3
    Per GitHub: Please use the Authorization HTTP header instead, as using the `access_token` query parameter is deprecated. If this token is being used by an app you don't have control over, be aware that it may stop working as a result of this deprecation. – BogeyMan Jun 24 '20 at 19:43
  • For a 3-line shell script not requiring API keys, curl or Python/Ruby, [my answer](https://stackoverflow.com/a/68770988/992887) might be useful. Based on the GitHub-supported `gh` CLI tool. – RichVel Aug 13 '21 at 10:54
71

Organisation repositories

To clone all repos from your organisation, try the following shell one-liner:

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

User repositories

Cloning all using Git repository URLs:

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

Cloning all using 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

Here is the useful shell function which can be added to user's startup files (using 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
}

Private repositories

If you need to clone the private repos, you can add Authorization token either in your header like:

-H 'Authorization: token <token>'

or pass it in the param (?access_token=TOKEN), for example:

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

Notes:

  • To fetch only private repositories, add type=private into your query string.
  • Another way is to use hub after configuring your API key.

See also:


Hints:
- To increase speed, set number of parallel processes by specifying -P parameter for xargs (-P4 = 4 processes).
- If you need to raise the GitHub limits, try authenticating by specifying your API key.
- Add --recursive to recurse into the registered submodules, and update any nested submodules within.

kenorb
  • 155,785
  • 88
  • 678
  • 743
  • 6
    per_page=1000 maxes out at 100 – aehlke Dec 27 '19 at 18:57
  • If it's not your own organization, try adding `sed 's/git@github.com:/https:\/\/github.com\//g'` as follows: `curl "GHORG=company; https://api.github.com/orgs/$GHORG/repos?per_page=1000" | grep -o 'git@[^"]*' | sed 's/git@github.com:/https:\/\/github.com\//g' | xargs -L1 git clone` – root Dec 19 '21 at 21:53
  • I modified the regex because I didn't have SSH keys set up so I go the following error: git@github.com: Permission denied (publickey). Modified command: `GHORG=company; curl "https://api.github.com/orgs/$GHORG/repos?per_page=1000" | grep -o "https://github.com/$GHORG/.*.git\b" | xargs -L1 git clone` – Ram Jul 27 '22 at 05:34
25

This gist accomplishes the task in one line on the command line:

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

Replace [your_org] with your organization's name. And set your per_page if necessary.

UPDATE:

As ATutorMe mentioned, the maximum page size is 100, according to the GitHub docs.

If you have more than 100 repos, you'll have to add a page parameter to your url and you can run the command for each 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"]} ]}'

Note: The default per_page parameter is 30.

kenorb
  • 155,785
  • 88
  • 678
  • 743
seancdavis
  • 2,739
  • 2
  • 26
  • 36
12

For anyone coming here on 2022:

First install this

gh extension install matt-bartel/gh-clone-org

Then here's a pretty simple command to achieve this

gh clone-org my_org_name

Github CLI now has an extension HERE. The first command is taken from here.

This extension helps to clone and update existing repositories by Organisation name.

It is suggested from Github CLI issues list HERE

Nazmul
  • 500
  • 6
  • 17
11

Use the Github CLI with some scripting to clone all (public or private) repos under a namespace

gh repo list OWNER --limit 1000 | awk '{print $1; }' | xargs -L1 gh repo clone

Where OWNER can be your user name or an org name.

Dennis
  • 56,821
  • 26
  • 143
  • 139
Purkhalo Alex
  • 3,309
  • 29
  • 27
9

So, I will add my answer too. :) (I found it's simple)

Fetch list (I've used "magento" company):

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

Use clone_url instead ssh_url to use HTTP access.

So, let's clone them all! :)

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

If you are going to fetch private repo's - just add GET parameter ?access_token=YOURTOKEN

Kirby
  • 2,847
  • 2
  • 32
  • 42
8

Go to Account Settings -> Application and create an API key
Then insert the API key, github instance url, and organization name in the script below

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

Save that in a file, chmod u+x the file, then run it.

Thanks to Arnaud for the ruby code.

Cory Klein
  • 51,188
  • 43
  • 183
  • 243
7

I found a comment in the gist @seancdavis provided to be very helpful, especially because like the original poster, I wanted to sync all the repos for quick access, however the vast majority of which were private.

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

Replace [[USERNAME]] with your github username and [[ORGANIZATION]] with your Github organization. The output (JSON repo metadata) will be passed to a simple ruby script:

# 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
Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
Garren S
  • 5,552
  • 3
  • 30
  • 45
  • 2
    This solution worked perfectly for me. Actually all I needed was to clone all of my personal account repos to my new local machine. Very handy for setting up new workstation. Note: to do this I had to change `.../orgs/[[organization]]/repos...` to `.../users/[[username]]/repos...`. Now I can quickly import all my work to different local machines. **THANKS!** – B. Bulpett Sep 26 '15 at 15:30
7

This python one-liner will do what you need. It:

  • checks github for your available repos
  • for each, makes a system call to 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'))]"
    
Barett
  • 5,826
  • 6
  • 51
  • 55
Evren Ozkan
  • 103
  • 1
  • 5
  • 2
    For python3 use -> `python -c "import json, urllib.request, os; [os.system('git clone ' + r['clone_url']) for r in json.load(urllib.request.urlopen('https://api.github.com/orgs/<>/repos?per_page=200'))]"` – thisisbhavin Dec 28 '21 at 17:45
7

Here is a Python solution:

curl -s https://api.github.com/users/org_name/repos?per_page=200 | python -c $'import json, sys, os\nfor repo in json.load(sys.stdin): os.system("git clone " + repo["clone_url"])'

Substitute org_name with the name of the organization or user whose repos you wish to download. In Windows you can run this in Git Bash. In case it cannot find python (not in your PATH etc.), the easiest solution I have found is to replace python with the path to the actual Python executable, for example: /c/ProgramData/Anaconda3/python for an Anaconda installation in Windows 10.

Filippos Zofakis
  • 561
  • 6
  • 12
6

I made a script with Python3 and Github APIv3

https://github.com/muhasturk/gitim

Just run

./gitim
muhasturk
  • 2,534
  • 20
  • 16
  • using this right now and it's doing exactly what I need it to do. ty for making it! you saved me a bunch of bs reinventing the wheel – snerd Feb 12 '23 at 18:35
5
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
halfelf
  • 9,737
  • 13
  • 54
  • 63
julianzhang
  • 51
  • 1
  • 1
4

I tried a few of the commands and tools above, but decided they were too much of a hassle, so I wrote another command-line tool to do this, called github-dl.

To use it (assuming you have nodejs installed)

npx github-dl -d /tmp/test wires

This would get a list of all the repo's from wires and write info into the test directory, using the authorisation details (user/pass) you provide on the CLI.

In detail, it

  1. Asks for auth (supports 2FA)
  2. Gets list of repos for user/org through Github API
  3. Does pagination for this, so more than 100 repo's supported

It does not actually clone the repos, but instead write a .txt file that you can pass into xargs to do the cloning, for example:

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

Maybe this is useful for you; it's just a few lines of JS so should be easy to adjust to your needs

wires
  • 4,718
  • 2
  • 35
  • 31
4

Clone all your public and private repos that are not forks:

Create first a Personal token for authentication, make sure it has all the repo permissions

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

Clone your gists:

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

This jq command is complex because gists' repo's name are hashes, so that command concatenates all filenames to be the repo's name


You can filter the JSON arbitrarily using jq

install: sudo apt-get install jq

In the example above, I filtered out forks using this: curl ... | jq -r 'map(select(.fork == false))' ... -- useful for not cloning repos where you've made casual pull requests

jq supports some very advanced features. man jq is your friend


Github's API urls

  • Your repos (needs authentication): https://api.github.com/user/repos\?page\=1\&per_page\=100
  • Any user: 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 for repos

Madacol
  • 3,611
  • 34
  • 33
3

So, in practice, if you want to clone all repos from the organization FOO which match BAR, you could use the one-liner below, which requires jq and common cli utilities

curl 'https://api.github.com/orgs/FOO/repos?access_token=SECRET' |
  jq '.[] |
  .ssh_url' |
  awk '/BAR/ {print "git clone " $0 " & "}' |
  sh
Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
konr
  • 2,545
  • 2
  • 20
  • 38
3

Simple solution:

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

There is also a very useful npm module to do this. It can not only clone, but pull as well (to update data you already have).

You just create config like this:

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

and do gitall clone for example. Or gitall pull

Vladislav Rastrusny
  • 29,378
  • 23
  • 95
  • 156
2

In case anyone looks for a Windows solution, here's a little function in PowerShell to do the trick (could be oneliner/alias if not the fact I need it to work both with and without 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() }
}
2

Another shell script with comments that clones all repositories (public and private) from a user:

#!/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
hlorand
  • 1,070
  • 10
  • 8
2

Create a bash alias/func in your ~/.bashrc file

I solved this for my team by creating an alias/bash func in my ~/.bashrc file

steps

open a terminal or linux shell and open your ~/.bashrc file:

sudo nano ~/.bashrc

add this function:

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
}

save and close your ~/.bashrc flile and then close the terminal -- you need to do this or the new func wont initialize:

open new terminal and try it out:

CloneAll <your_github_org_name>

example: if your personal github repo URL is called https://github.com/awesome-async the command would be

CloneAll awesome-async

Important

the per_page=200 at the end of the first variable ORG_URL sets the number of repos that will be cloned, so pay special attention to that:

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

Hope this helps! :)

Flavio
  • 506
  • 4
  • 9
  • Seems max. value for per_page is 100 ... for large orgs added page number as 2nd parameter and it works perfectly for my needs `...repos?page=${2}&per_page=100"; ` – sv3n Jul 29 '20 at 00:57
2

We can use gh now and it clone 5 repo parallely

export org=<org|gh-handle>
gh repo list $org | cut -f1 | xargs -n 1 -P 5 gh repo clone

For more parallel task we can increase -P 5 to any number we want

razzkumar
  • 431
  • 3
  • 4
2

The easier way is to use github cli to get the ssh url and clone using the git command.

gh repo list --json sshUrl --jq '.[].sshUrl' | xargs -n1 git clone
Jansen
  • 46
  • 3
1

You can get a list of the repositories by using curl and then iterate over said list with a bash loop:

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
jotasi
  • 5,077
  • 2
  • 29
  • 51
1

You can use open-source tool to clone bunch of github repositories: https://github.com/artiomn/git_cloner

Example:

git_cloner --type github --owner octocat --login user --password user https://my_bitbucket

Use JSON API from api.github.com. You can see the code example in the github documentation: https://developer.github.com/v3/

Or there:

https://github.com/artiomn/git_cloner/blob/master/src/git_cloner/github.py

A.N.
  • 278
  • 2
  • 13
1

To clone only private repos, given an access key, and given python 3 and requests module installed:

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;
ubugnu
  • 1,004
  • 2
  • 15
  • 30
1

A Python3 solution that includes exhaustive pagination via Link Header.

Pre-requisites:


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

Then, you can use xargs or parallel and: cat repolist | parallel -I% hub clone %

Jose Alban
  • 7,286
  • 2
  • 34
  • 19
1

If you have list of repositories in a list like this, then this shell script works:

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

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

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

do

   echo $user"$i"

   git clone $user"$i"

done 
Nick
  • 4,820
  • 18
  • 31
  • 47
1

I created a sample batch script. You can download all private/public repositories from github.com. After a repository is downloaded, it is automatically converted to a zip file.

@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 ..
)

Note: files.txt file should contain only repository names like:

repository1
repository2
olyanren
  • 1,448
  • 4
  • 24
  • 42
1

The prevailing answers here don't take into account that the Github API will only return a maximum of 100 repositories despite what you may specify in per_page. If you are cloning a Github org with more than 100 repositories, you will have to follow the paging links in the API response.

I wrote a CLI tool to do just that:

clone-github-org -o myorg

This will clone all repositories in the myorg organization to the current working directory.

Chad
  • 2,378
  • 2
  • 26
  • 27
1

For orgs you have access to with private repos:

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

It uses the html_url, so you don't need an access_token just enter your github password when prompted.

Flavio
  • 506
  • 4
  • 9
  • 2
    Basic authentication using a password to the API is deprecated and will soon no longer work. Visit [deprecating-password-auth] (https://developer.github.com/changes/2020-02-14-deprecating-password-auth/) for more information around suggested workarounds and removal dates. – BogeyMan Jun 24 '20 at 19:19
1
"""
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']}...")
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
1

To clone all your own private and public repos simple generate a new access token with repos access and use this:

(replace with your own access token and username)

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

This will clone all repos in current folder

This is a little bash program, you can just paste it in the terminal and hit enter

Basel Akasha
  • 1,108
  • 1
  • 11
  • 25
1

You could use a tool like GitHub Archive which allows you to clone/pull public and private personal repos, organization repos, and gists all with one simple tool.

As for automation, you could then set up GitHub Archive to run once a day or once a week for example and it will skip those that are cloned and pull in new changes since the last time it was run of all others.

Source: https://github.com/Justintime50/github-archive

Justin Hammond
  • 595
  • 8
  • 20
1

When I want to clone all my repos fast I do:

for i in `echo https://github.com/user/{repox,repoy,repoz,repob}`; do git clone $i; done
Nickotine
  • 167
  • 6
1

Here's a way to get all of a user's gists that takes into account github's new api and pageation rules...

usage:

python3 gist.py bgoonz

Also ... every clone is going to be it's own repo which can get pretty memory intensive on your drive... you can remove the git repos recursively using:


find . \( -name ".git" -o -name ".gitignore" -o -name ".gitmodules" -o -name ".gitattributes" \) -exec rm -rf -- {} +

If you want to clone them all into an existing repository of yours... make sure you aren't in the outermost folder of your repo when you run this command or it will delete your .git folder just as indiscriminately as it will delete the ones that belong to the gists.

Language:Python

#!/usr/bin/env python3

import os
import sys
import json
import hashlib
import requests

from subprocess import call
from concurrent.futures import ThreadPoolExecutor as PoolExecutor

def download_all_from_user(user: str):
    
    next_page = True
    page = 1
    
    while next_page:
        
        url = f"https://api.github.com/users/{user}/gists?page={page}"
        
        response = requests.get(url)

        if not len(response.json()):
            next_page = False
        else:
            page += 1

        download_all(response.json())

def download_all(gists: list):
    with PoolExecutor(max_workers=10) as executor:
        for _ in executor.map(download, gists):
            pass

def download(gist):
    
    target = gist["id"] + hashlib.md5(gist["updated_at"].encode('utf-8')).hexdigest()
    
    call(["git", "clone", gist["git_pull_url"], target])

    description_file = os.path.join(target, "description.txt")
    
    with open(description_file, "w") as f:
        f.write(f"{gist['description']}\n")

# Run

user = sys.argv[1]

download_all_from_user(user)
1

I wanted to suggest another option, which may be easier than some of the scripts posted here. mergestat is a command-line tool that can be used to clone all org repositories from GitHub, as described on this page.

mergestat "SELECT clone('https://github.com/mergestat/'|| name) AS path FROM github_org_repos('mergestat')" -v --clone-dir my-dir

This is not the primary purpose of the tool, but is a useful side-effect of what it does (it's a way to query git repositories with SQL). Full disclosure, I am the maintainer/creator, but wanted to share here as this is a fairly frequent use-case/question we get from users, and I hope mergestat can provide a simple solution to it.

Patrick DeVivo
  • 755
  • 1
  • 9
  • 13
1

Update from 2023:

if you would like to make it easier and using http_url not ssh_url or without any overhead complicated solutions use this simple one: replace USERNAME with name that you would like:

curl -s https://api.github.com/users/{USERNAME}/repos?per_page=100 | jq -r ".[].clone_url" | xargs -L1 git clone

the max per_page is 100 as in Github doc. if you would like more think about creating iteration loop.

0

Update from May 19

use this bash command for an organization (private repo included)

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

Similar to others, I also wrote a utility tool for exporting github data. Different to others, it loads paginated data from github, so more than 100 repos/other list data at once, and also supports downloading many additional pieces of data, such as cloning repos with all branches, downloading issues and PRs as JSON and HTML reports, downloading lists of your starred repos and more.

You can use it via

npx github-takeout

or download binaries from here. You can find out more about what it does and how it works at https://github.com/lukasbach/github-takeout/

Lukas Bach
  • 3,559
  • 2
  • 27
  • 31
0

A simple solution in Powershell using the github CLI

get the GitHub CLI tool https://github.com/cli/cli/releases/ Then

gh auth login

Follow instructions on screen then

Replace [org] with your org name and execute the following.

 gh repo list [org] --limit 1000 | % {[String]$repo, [String]$trash = $_ -split "\s",2
    gh repo clone "$repo" "$repo" }
Adam Wheeler
  • 393
  • 1
  • 11
0

The easiest way to download all with the same method mentioned by @RichVel under Windows is by install gh and then running the following powershell script:

gh repo list TeamName --limit 1000 | Tee-Object -Variable result
foreach ($item in $result){
    $repo = $item.Split("`t")[0]
    gh repo clone $repo $repo
}
KevinK
  • 13
  • 2
0

This works fine in Windows, create a clone.bat file

FOR /F "tokens=*" %%i IN ('gh repo list <organization-name> --json name --jq ".[] | .name"') DO (
    gh repo clone <organization-name>/%%i
)
Merlyn007
  • 434
  • 1
  • 8
  • 21
-1

An easy way to grab the list of repository names is to browse to the page listing the repos of the org in your web browser and extracting it via JavaScript:

Array.from(document.querySelectorAll('[itemprop="name codeRepository"]')).map(function(item){ return item.text.replace(/\s/g,'') })

You can easily adapt this code to generate the actual git clone commands if you like.

The advantage of this is that you don't need to bother with API keys or command line extractions.

A possible disadvantage is that you might need to change this code if Github changes their site design or code.

thomasfuchs
  • 5,386
  • 2
  • 18
  • 38
-2

Here is the windows version using PowerShell

$name="facebook" #either username or org_name

$api_url="https://api.github.com/users/$($name)/repos?per_page=200"

$repos=Invoke-WebRequest -UseBasicParsing -Uri $api_url |ConvertFrom-Json

foreach ($repo in $repos)
{
  Write-Host  "Cloning via SSH URL  $($repo.ssh_url)"
  git clone $repo.ssh_url
}
Suman Saurabh
  • 401
  • 5
  • 9