Bassam Ismail

Deleting all your GitHub forks

12 October, 2023

github

Today while I was doing a routine cleanup of my account I noticed there were a lot of forked repository. I hadn’t cleaned up in a while and now I had to manually delete 21 repositories. I deleted a few of them to quickly realize that the task wasn’t tenable.

Screenshot of Bassam’s Github filtered by Forked repositories

So I started exploring the Github REST API and figured out that after generating a token (with the required read_repo and delete_repo permissions) I needed to call two end points to delete all the forks.

At the top of the REST docs it is recommended to authenticate using the gh CLI tool to use the API. This got me thinking. What if I could get all the forks using gh? and what if I could delete all of them using it?

To get the list of all forked repositories:

$ gh repo list --fork

There is a different command to delete repositories.

$ gh repo delete skippednote/skippednote

We can pass it a --yes flag to make it non-interactive. However, the flag should be append instead of it preceding the repository name.

$ gh repo delete skippednote/skippednote --yes

Now to delete all the forked repositories, we just need to iterate over the list generated from the gh repo list --fork command and pass them to gh repo delete.

$ gh repo list --fork | xargs -I {} gh repo delete {} --yes

This, however, doesn’t work as the output from gh repo list --fork is table and we need to pass gh repo delete a repo name.

Luckily, there is a flag (--json) to render the list as JSON and then we can query the data using the jq flag to pull out the name using a jq query. This will delete all our forked repositories one by one 🥳.

$ gh repo list --fork --json name -q '.[] | .name' | xargs -I {}  gh repo delete {} --yes

If you are feeling adventurous or have a lot more repositories to delete, you can run delete repositories in parallel using xargs -P 8. This way you can have 8 processes running in parallel.

$ gh repo list --fork --json name -q '.[] | .name' | xargs -P8 -I {}  gh repo delete {} --yes