Organize Your Github  Like A Pro With This Python Script
Tags: python, productivity, lifehacks, automation
Published: 2020-09-09 11:41:06

## What? Why?

You and I use GitHub every day and if you are anything like me very often come across an interesting repo, quickly fork it and save it for playing with it at some point later in the future, sometimes distant future :) 

My GitHub started looking a little too cluttered with these Repos so I decided to do some cleaning. Yes, you could use the browser to point, click, copy, and paste every single repo you want to transfer out of your main account into another one to keep to interesting Repos safe and maintain your main account looking professional, but I find that very time consuming and just plainly bad use of the time we could instead use for twitting and be on our way to becoming social media influencers. 

## How? Here is what we need to get started

We'll use the GitHub API to automate this task :robot:, Python with a virtual environment for our script and the requests library to talk to the API. 

- First head out to [GitHub](https://github.com/settings/tokens) and generate a personal access token from the developer settings page. On this page, click Generate a new token, give your token a name and select the scopes you need. I selected all the repo scopes because I'm planning on extending this utility. Here are the [docs](https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/) for a more detailed dive into scopes.

![scopes](https://dev-to-uploads.s3.amazonaws.com/i/xfgc7lc3ymvi8usygrtz.png)

Copy the token and test quickly test it out with curl.

```bash
~ $ GITHUB_TOKEN="access_token"
~ $ curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/gists
```
If it worked you should receive a similar repose with a list of all your public Gists.

```bash
[
 {
    "url": "https://api.github.com/gists/4d5ab8adff9fc8b4cdf7d8e9dfa442c7",
    "forks_url": "https://api.github.com/gists/4d5ab8adff9fc8b4cdf7d8e9dfa442c7/forks",
    "commits_url": "https://api.github.com/gists/4d5ab8adff9fc8b4cdf7d8e9dfa442c7/commits",
    "id": "4d5ab8adff9fc8b4cdf7d8e9dfa442c7",
    "node_id": "MDQ6R2lzdDRkNWFiOGFkZmY5ZmM4YjRjZGY3ZDhlOWRmYTQ0MmM3",
    "git_pull_url": "https://gist.github.com/4d5ab8adff9fc8b4cdf7d8e9dfa442c7.git",
    "git_push_url": "https://gist.github.com/4d5ab8adff9fc8b4cdf7d8e9dfa442c7.git",
    "html_url": "https://gist.github.com/4d5ab8adff9fc8b4cdf7d8e9dfa442c7",
    "files": {
      "views.py": {
        "filename": "views.py",
        "type": "application/x-python",
        "language": "Python",
        "raw_url": "https://gist.githubusercontent.com/jqn/4d5ab8adff9fc8b4cdf7d8e9dfa442c7/raw/7acabeae8db34dcae72fbb1dbb002557a70632ef/views.py",
        "size": 347
      }
    },
...
]
```

- The second thing we need is a Virtual Environment. If you are a beginner or just unsure on how to do this please give this a read [Learn How To Get Started With Flask](https://medium.com/@jQN/getting-started-with-flask-a53198e11012?source=friends_link&sk=dfce26cf7df6b143b58f5b572bb7e5ba) It's geared towards getting you started with Flask but it goes over how to configure a local Python development environment.

I use [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/)

```bash
$ mkdir ~/www/automation
$ cd ~/www/automation
$ mkvirtualenv automation_hacks
(automation) $ automation
```

Now with a Virtual Environment ready let's get the coding started.

- Create a new Python script and install the required packages. Inside the automation directory run the following commands.

```bash
$ touch github_hacks.py
$ pip install requests
$ pip freeze > requirements.txt
```

This is the current directory structure

```
automation
├── github_hacks.py
└── requirements.txt
```
And with [VSCode](https://code.visualstudio.com/)

```
$ code github_hacks.py
```
[VSCode](https://code.visualstudio.com/) is not required for this step so feel free to use your favorite text editor.

- And now "The code"

```python
import requests
import sys
from pprint import pprint
import json

token = "access_token"
owner = sys.argv[1]
repo = sys.argv[2]
new_owner = sys.argv[3]


query_url = f"https://api.github.com/repos/{owner}/{repo}/transfer"

headers = {'Authorization': f'token {token}',
           'Accept': 'application/vnd.github.v3+json'}
params = {
    'new_owner': new_owner,
}

r = requests.post(query_url, headers=headers, data=json.dumps(params))

pprint(r.json())

```

- Finally, we can run it like this:

`$ python github_hacks.py owner repo new_owner`

If you go back to your GitHub the repo was transferred to the new owner.

Currently, this script takes a single Repo at the time but it can be expanded to take multiple Repos and transfer them to another owner/organization.

This works best when transferring to an organization you own. If transferring to a new owner the owner has to accept the transfer first. 

I did tryout [PyGithub](https://github.com/PyGithub/PyGithub) but currently, it doesn't have the transfer repo feature. There are also other ready to use libraries listed in the Github API [docs](https://docs.github.com/en/rest/overview/libraries) but most of them are outdated as of the writing of this article.

Questions? Problems? Don't hesitate to reach out on [Twitter](https://twitter.com/jQNReactor) or comment below. 

## Resources
[Github Developer - Scopes](https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)

[Github Rest API](https://docs.github.com/rest/reference/repos#transfer-a-repository)

[requests](https://requests.readthedocs.io/en/latest/user/quickstart/)

[f-string Formatting in Python](https://www.datacamp.com/community/tutorials/f-string-formatting-in-python#SC)