🚀 Executive Summary

TL;DR: This guide addresses the problem of managing development across both Bitbucket and GitHub by providing a streamlined, two-command process to migrate repositories. It details how to perfectly transfer all Git history, branches, and tags from Bitbucket to an empty GitHub repository, unifying development workflows.

🎯 Key Takeaways

  • Use `git clone –bare` to create a full mirror of the Bitbucket repository, capturing all commits, branches, and tags without a working directory.
  • Employ `git push –mirror` to push the entire mirrored history, including all references, to the new GitHub repository.
  • Always create a completely empty GitHub repository as the target to avoid ‘unrelated histories’ errors during the push.
  • A GitHub Personal Access Token (PAT) with `repo` scope is required for authentication when pushing to GitHub.
  • Configuring SSH URLs for both cloning and pushing can streamline the process by eliminating repeated credential entry.

Migrate Bitbucket Repositories to GitHub (Including Branches/Tags)

Migrate Bitbucket Repositories to GitHub (Including Branches/Tags)

Hey there, Darian Vance here. Let’s get straight to it. For a long time at TechResolve, we had a split-brain problem: legacy projects on Bitbucket, new stuff on GitHub. Juggling two platforms for pull requests, CI/CD pipelines, and security scanning was a massive time sink. Consolidating everything into GitHub streamlined our entire workflow, and frankly, made my life easier. This isn’t just about moving files; it’s about unifying your development ecosystem. If you’re looking to do the same, this is the exact, no-frills process I use to migrate a repository perfectly, history and all, in under five minutes.

Prerequisites

Before we start, make sure you have the following ready. A little prep saves a lot of troubleshooting.

  • Git CLI: You’ll need Git installed on your local machine.
  • Bitbucket Repository URL: The HTTPS or SSH clone URL for the repository you want to migrate.
  • An Empty GitHub Repository: Go to GitHub and create a new, completely empty repository. Do not initialize it with a README, license, or .gitignore file.
  • GitHub Personal Access Token (PAT): You’ll need a PAT with `repo` scope to authenticate the push to your new GitHub repository. Treat this like a password.

The Step-by-Step Migration Guide

This process is all about creating a perfect, mirrored copy of the Git data itself, not just the files in the main branch. We’ll do this by performing a “bare” clone.

Step 1: Create a Full Mirror of the Bitbucket Repository

First, open your terminal. We’re not going to do a standard `git clone`. Instead, we’ll use the `–bare` flag. This downloads the entire Git object database—all the commits, branches, and tags—without creating a working directory with the actual files. It’s like copying the brain of the repository.

Navigate to a folder where you want to temporarily store the repository data and run this command:

git clone --bare https://bitbucket.org/your-workspace/your-repo.git

This will create a new directory named `your-repo.git`. All of our next steps will happen inside that directory.

Pro Tip: Using a bare clone is non-negotiable for a true migration. A regular clone only checks out the default branch and its history, leaving all your other feature branches and tags behind. The `–bare` flag ensures you get everything.

Step 2: Push the Mirrored Repository to GitHub

Now, navigate into the directory you just created. I’ll skip the standard `cd` command, as you know how to navigate your own terminal. Once you are inside the `your-repo.git` directory, we’re going to push this entire mirrored history to its new home on GitHub.

We’ll use the `–mirror` flag for the push. This ensures that every single reference (branches, tags, etc.) from your local bare repository is pushed to the new remote.

git push --mirror https://github.com/your-username/your-new-repo.git

When prompted, use your GitHub username and your Personal Access Token (PAT) as the password.

Once that command finishes, you’re done. Refresh your GitHub repository page. You should see all your files, your full commit history, and if you check the branches/tags dropdown, every single one will be there.

Pro Tip: In my production setups, I always use SSH URLs instead of HTTPS for both cloning and pushing. It saves me from having to enter credentials every time. If your SSH keys are configured correctly in both Bitbucket and GitHub, the process is even smoother.

Step 3: Clean Up

Since we created a temporary local copy, you can now safely delete the `your-repo.git` folder from your machine. The source of truth is now on GitHub.

Common Pitfalls (Where I’ve Messed Up Before)

  • Pushing to a Non-Empty Repo: I can’t stress this enough. If you initialize your new GitHub repo with a README, it creates an initial commit. Trying to push your mirrored history on top of that will lead to errors about unrelated histories. Always start with a completely blank slate on the GitHub side.
  • Incorrect PAT Permissions: If your push fails with an authentication error, the first thing to check is your GitHub PAT. Ensure it has the full `repo` scope enabled. A token without the right permissions won’t be able to write to the repository.
  • Forgetting `–mirror` on the Push: A regular `git push` will only send up your default branch. The `–mirror` flag is what tells Git to push all refs (branches and tags). Forgetting it means you’ll only get a fraction of your repository’s history.

Conclusion

And that’s the whole playbook. Two commands are all it takes to perform a clean, complete migration from Bitbucket to GitHub. By using the `bare` clone and `mirror` push, you guarantee that not a single commit, branch, or tag is left behind. In our team at TechResolve, standardizing these small, repeatable processes is what allows us to move quickly and avoid costly mistakes. Hopefully, this one saves you some time and a few headaches.

Darian Vance - Lead Cloud Architect

Darian Vance

Lead Cloud Architect & DevOps Strategist

With over 12 years in system architecture and automation, Darian specializes in simplifying complex cloud infrastructures. An advocate for open-source solutions, he founded TechResolve to provide engineers with actionable, battle-tested troubleshooting guides and robust software alternatives.


🤖 Frequently Asked Questions

âť“ What is the essential command-line process to migrate a Bitbucket repository to GitHub, ensuring all history, branches, and tags are preserved?

First, create a bare clone of the Bitbucket repository using `git clone –bare `. Then, navigate into the created `.git` directory and push the mirrored content to an empty GitHub repository using `git push –mirror `, authenticating with a GitHub Personal Access Token.

âť“ How does this direct Git CLI migration method compare to other repository migration tools or services?

This direct Git CLI method offers precise control and guarantees a perfect, mirrored copy of all Git data using standard commands. While other tools might provide more automation or UI, this approach is highly reliable for ensuring full history preservation and avoiding partial migrations, making it ideal for critical transfers.

âť“ What is a common implementation pitfall during this migration process and how can it be avoided?

A common pitfall is pushing to a GitHub repository that was initialized with a README, license, or .gitignore, which creates an initial commit and leads to ‘unrelated histories’ errors. This can be avoided by always creating a completely blank, empty GitHub repository as the target for the migration.

Leave a Reply

Discover more from TechResolve - SaaS Troubleshooting & Software Alternatives

Subscribe now to keep reading and get access to the full archive.

Continue reading