Migrating Repos in Bulk from Gitea to Github

I recently fell victim to the conveniences of big tech (at least temporarily), and was faced with the task of migrating hundreds of my personal git repositories from my self-hosted Gitea instance to Github. With this many repos to migrate, completing any part of this migration manually wasn’t really an option. Instead, I leveraged the Gitea and Github APIs to automate the whole process.

First, I created an auth token on Gitea for use with the Gitea API and setup the Github CLI. Next, I used the Gitea API to retrieve repository info. You’ll need to call this multiple times and paginate manually if you have more than 50 repos under a single entity.

For repositories under organizations:

1
curl -k -u "<ORG_NAME>:<GITEA_TOKEN>" "https://<YOUR_GITEA_URL>/api/v1/orgs/<ORG_NAME>/repos?limit=50&page=1" >> <ORG_NAME>.json

For repositories under my profile:

1
curl -k -u "<USERNAME>:<GITEA_TOKEN>" "https:/<YOUR_GITEA_URL>/api/v1/users/<USERNAME>/repos?limit=50&page=1" >> <USERNAME>.json

If you don’t care about organization and just want everything your user account has access to on Gitea:

1
curl -k -u "<USERNAME>:<GITEA_TOKEN>" "https://<YOUR_GITEA_URL>/api/v1/user/repos?limit=50&page=1" >> <USERNAME>.json

Next, for each entity to migrate, I cloned each repo. If you have multiple branches you want to preserve, you’ll need to do a full clone instead of this.

1
2
mkdir <USERNAME> && cd <USERNAME>
jq -r '.[].name' ../<USERNAME>.json | while read i; do git clone git@<YOUR_GITEA_URL>:<USERNAME>/$i.git; done

Finally, I used gh, the Github CLI, to create new private repositories preserving the old names and descriptions:

1
2
jq -r '.[] | "gh repo create \(.name) --private --description=\"\(.description)\""' ../<USERNAME>.json | while read i; do eval $i; done
jq -r '.[] | "cd \(.name) && git remote set-url origin git@github.com:<GITHUB_USERNAME>/\(.name).git && git push && cd .."' ../<USERNAME>.json | while read i; do eval $i; done

As part of this migration, I also marked all repositories I wasn’t actively working on anymore (ie. everything in Github pre-migration) as archived, also using gh:

1
2
gh repo list -L 100 --json name >> github_repos_to_archive.json
jq -r '.[].name' github_repos_to_archive.json | while read i; do gh repo archive $i -y; done

Leave a Reply

Your email address will not be published. Required fields are marked *