A Universal Guide to Migrating Git Repositories with LFS Across Platforms

Have you ever faced the daunting task of migrating a Git repository complete with LFS files? Recently, I embarked on this journey from Bitbucket to GitLab and hit a few snags along the way. In this post, I'll share the motivations, challenges, and ultimately the steps that led to a successful migration. Plus, some troubleshooting advice for any developer who might walk this path in the future.

The Path Less Traveled: Why This Approach?

My journey began with the need to move a repository from Bitbucket Server to GitLab. I initially tried GitLab's import feature, which is conveniently available when creating a new repo. However, this seemingly smooth road had a couple of potholes:

  1. GitLab's import tool failed to correctly handle Git LFS files from Bitbucket

  2. The feature doesn't work if the GitLab repository already exists, as it's only available during the creation of a new repo.

These hurdles necessitated a different approach.

Prerequisites

Before you dive into the migration process, ensure you have:

  • Read access to the old repository (Bitbucket in my case)

  • Write access to the new repository (GitLab)

  • Git and Git LFS installed on your local machine

Migration Steps

Here's a distilled version of the migration process, including the handling of Git LFS files:

1. Clone the Old Repository

Start by making a bare clone of the Bitbucket repository and navigate into the repository directory:

git clone --mirror <source-repo-URL>
cd <name-of-repo>.git

Replace <source-repo-URL> with the URL of the repository you're migrating from. This command creates a bare clone—a full copy of the repo data sans a working directory.

2. Add the GitLab Repository as a Remote

Add your new GitLab repository as a remote:

git remote add new_remote <new-repo-URL>

Assign your target repository as the new remote. Replace <new-repo-URL> with your destination repository's URL.

4. Handle LFS Files

Fetch all LFS files:

git lfs fetch --all

Then, push them to their new home:

git lfs push --all new_remote

5. Push to the New Repository

git push --mirror gitlab

Troubleshooting Common Roadblocks

  • Protected Branches: Temporarily unprotect branches in the destination repo settings if the push is blocked.

  • Default Branch: Temporarily remove the default branch in the destination repo settings if the push is blocked.

Final Thoughts

This migration method is a reliable fallback when conventional tools fail, especially for complex repositories with LFS files. It's a powerful approach that transfers the entirety of your repository's history to any platform of your choice. Just remember, with great power comes great responsibility: ensure you're ready to overwrite the destination before you unleash the --mirror command.

Happy coding, and may your migrations be ever in your favour!