GitHub Syncer in Python

Today I rewrote a little utility I've been using for a while to keep all of my GitHub repos up to date and organized. It updates / clones all private, public, and watched repositories from your account. It also detects if your repo is a mirror or fork, and files it accordingly. My watched list is huge, but I like to have a local copy of my favorite libraries. You never know if the owner will take it down, or worse, move it to another SCM! ;-)

The script depends on the **GitHub2** module. If you don't have it, you can install it easily.

$ pip install github2

I recommend running this from `~/repos/`.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Kenneth Reitz's GitHub Syncer

This script uses the GitHub API to get a list of all forked, mirrored, public, and 
private repos in your GitHub account. If the repo already exists locally, it will 
update it via git-pull. Otherwise, it will properly clone the repo.

It will organize your repos into the following directory structure:

+ repos
  ├── forks    (public fork repos)
  ├── mirrors  (public mirror repos)
  ├── private  (private repos)
  ├── public   (public repos)
  ├── watched  (this script)
  └──  (this script)

Requires Ask Solem's github2 (

Inspired by Gisty ( 

import os
from commands import getoutput as cmd

from github2.client import Github

# GitHub configurations
GITHUB_USER = cmd('git config github.user')
GITHUB_TOKEN = cmd('git config github.token')

# API Object
github = Github(username=GITHUB_USER, api_token=GITHUB_TOKEN)

# repo slots
repos = {}

repos['watched'] = [r for r in github.repos.watching(GITHUB_USER)]
repos['private'] = []
repos['mirrors'] = []
repos['public'] = []
repos['forks'] = []

# Collect GitHub repos via API
for repo in github.repos.list():

    if repo.private:
    elif repo.fork:
    elif 'mirror' in repo.description.lower():
        # mirrors owned by self if mirror in description...

for org, repos in repos.iteritems():
    for repo in repos:

        # create org directory (safely)
        except OSError:

        # enter org dir

        # I own the repo
        private = True if org in ('private', 'fork', 'mirror') else False

        # just `git pull` if it's already there
        if os.path.exists(
            print('Updating repo: %s' % (
            os.system('git pull')
            if private:
                print('Cloning private repo: %s' % (
                os.system('git clone' % (repo.owner,
                print('Cloning repo: %s' % (
                os.system('git clone git://' % (repo.owner,

        # return to base

[Source on GitHub](