POSTS

Syncing Public GitLab Projects to GitHub

set up your access and tools

You’ll need

clone the projects

usage

export GL_TOKEN='yourtokenhere'
export GL_URL='https://gitlab.com'
virtualenv -p python3 venv
. venv/bin/activate
pip install python-gitlab
python main.py

main.py

import os
import sys
import gitlab
import subprocess

gl = gitlab.Gitlab(os.getenv('GL_URL'), os.getenv('GL_TOKEN'))

owned_projects = gl.projects.list(owned=True, all=True, visibility='public')

print ('i own {} projects'.format(len(owned_projects)))

projects_dir = '/path/to/dir/to/clone/to'

for project in owned_projects:
    print('cloning {}'.format(project.name))
    command = 'git clone {} {}/{}'.format(project.ssh_url_to_repo, projects_dir, project.name)
    process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    output, _ = process.communicate()
    process.wait()

some notes

Apparently GitLab projects are organized by namespace, which is a dict with a field kind, which is user for user projects and group for group projects.

The gl.groups call returns all projects linked to that group. With this list, it’s possible to get the git clone url. I suppose this is technically correct, but it ignores all projects in the default user space.

I’m pretty sure gl.projects.list(all=True) tries to retrieve all of GitLab’s publicly visible projects, not just yours. Don’t do that.

gl.projects.list(owned=True, all=True, visibility='public') seems to return just publicly visible projects owned by me, without needing to worry about group vs. user namespaces.

push the projects to GitHub

This is probably better served as a bash script to allow more control for conflicts and other problems, but this works as a quick solution.

One downside to this approach is that it’s not always clear which directory is currently being acted on for repo creation and pushing.

change all remote URLs from GitLab to GitHub

This is a bit messy, but basically, it’s using basename to get the name of the directory (which is the name of the GitLab project), storing it in THE_NAME, then updating the remote with GitHub’s url string, substituting THE_NAME for the project.

for f in *; do THE_NAME=$(basename $f) && (cd $f && git remote set-url origin git@github.com:modle/$THE_NAME.git); done

create the necessary repos in GitHub using the hub tool

It’s not possible to create a repo in GitHub with a git push, so tools like hub are needed to automate this step.

Hub will ask for your username and password, though there may be an API token setting. It will also warn you if the target repo already exists: Existing repository detected.

The usage docs for hub state that hub create will also set the remote URL for the directory, but it (rightly so) does not do this when a remote is already defined, hence the update remote URL command above.

for f in *; do (cd $f && hub create); done

push repo to GitHub

for f in *; do (cd $f && git push); done