Migrate a repository from GitLab to GitHub

Migrate a repository from GitLab to GitHub
Photo by Julia Craice / Unsplash

How to migrate a set of repositories from GitLab to GitHub while only pushing the current state of the project (without previous commit history).

This script will:

  1. Retrieve all your repositories from GitLab.
  2. For each repository:
    • Clone it using the SSH URL from GitLab.
    • Create a new repository on GitHub.
    • Initialize a new local repository, add all files, and make an initial commit.
    • Push this new repository to GitHub, starting with a single initial commit.

Before running this script, make sure:

  • You have SSH keys set up and added to both your GitLab and GitHub accounts.
  • git and Python are installed on your machine.
  • The requests library is installed in Python (install with pip install requests).

Here's the script:

import os
import requests

# Your personal access tokens
GITLAB_TOKEN = 'your_gitlab_token'
GITHUB_TOKEN = 'your_github_token'

# Your GitLab and GitHub usernames
GITLAB_USERNAME = 'your_gitlab_username'
GITHUB_USERNAME = 'your_github_username'

# API Endpoints
GITLAB_API = 'https://gitlab.com/api/v4'
GITHUB_API = 'https://api.github.com'

# Get list of GitLab repositories
def get_gitlab_repos(username, token):
    repos = []
    page = 1
    per_page = 100

    while True:
        response = requests.get(f"{GITLAB_API}/users/{username}/projects?page={page}&per_page={per_page}", 
                                headers={"PRIVATE-TOKEN": token})
        page_repos = response.json()

        if not page_repos:
            break

        repos.extend(page_repos)
        page += 1

    return repos

# Create GitHub repository
def create_github_repo(name, token):
    headers = {
        'Authorization': f'token {token}',
        'Accept': 'application/vnd.github.v3+json',
    }
    data = {
        'name': name,
        'private': True
    }
    response = requests.post(f"{GITHUB_API}/user/repos", headers=headers, json=data)
    return response.json()

# Clone and push the repository with only the latest state (no history)
def clone_and_push(gitlab_ssh_url, github_ssh_url):
    repo_name = gitlab_ssh_url.split(':')[-1].split('.')[0]
    os.system(f"git clone {gitlab_ssh_url}")
    os.chdir(repo_name)
    os.system("rm -rf .git")
    os.system("git init")
    os.system("git add .")
    os.system('git commit -m "Initial commit"')
    os.system(f"git remote add origin {github_ssh_url}")
    os.system("git push -u origin main")
    os.chdir('..')

def main():
    gitlab_repos = get_gitlab_repos(GITLAB_USERNAME, GITLAB_TOKEN)

    for repo in gitlab_repos:
        print(f"Migrating {repo['name']}...")

        gitlab_ssh_url = f"git@gitlab.com:{GITLAB_USERNAME}/{repo['path_with_namespace']}.git"
        new_repo = create_github_repo(repo['name'], GITHUB_TOKEN)
        github_ssh_url = f"git@github.com:{GITHUB_USERNAME}/{repo['name']}.git"

        clone_and_push(gitlab_ssh_url, github_ssh_url)

if __name__ == "__main__":
    main()

How to Use This Script:

  1. Replace 'your_gitlab_token', 'your_github_token', 'your_gitlab_username', and 'your_github_username' with your actual credentials and usernames.
  2. Run the script. It will clone each GitLab repository, create a corresponding new repository on GitHub, and push a single commit with the current state of each project.
  3. Test with one repository initially to ensure it works as expected in your environment.

This script assumes your SSH keys are correctly configured for both GitLab and GitHub. If you encounter any issues, they might be related to your SSH key setup or network permissions.

Have fun!