There are several options for migrating repos to GitHub, depending on what Source Control Management (SCM) tool you are coming from, and what you want to migrate. Just the Git repo with all of its history? Because it’s Git to Git, it’s easy Only care about the latest changes and want to start fresh? Perhaps even easier, pull or get latest, create a new Git repo, add in the changes, and push. If it’s not Git, you must determine if you want to use a specialized tool to migrate or start fresh. This post will cover all of the different options, when you should use them, and any known gotchas.
Often, simply migrating your entire Git repository (with history) is sufficient and the most recommended approach. If you need to persist the metadata of your issues and pull requests comments for audit purposes, one option is to leave around the old system in a read-only state until it can be retired.
The way that GitHub attributes commits to an author is via the email address in the
git config. In GitHub, you can add multiple email addresses, and if you want to see your GitHub avatar show up next to your commits, make sure to add your email address to your GitHub account.
Look at the example below. The first edit I made in GitHub.com, so it shows up as me. The second edit I made on my local machine, and since my
git config was set up without using an email address linked to my GitHub account, the commit does not show up as from me:
Since the email in my Git config isn’t added to my GitHub account, the commit doesn’t link to my profile
To summarize, use
git config --global --edit to view/update your local Git config and make sure the email address listed here is also added in GitHub.
I often forget about this one, and if your repo is on a SAAS service (like Azure DevOps, BitBucket Cloud, etc.), this is going to be the way to go. The GitHub Importer works with Git, SVN, and Mercurial. This tool will import the contents of the repository, including history. For repos that require authentication, the wizard walks you through providing that information (typically a personal access token or API key). I’ve personally used this for migrating Azure DevOps Git repos as well as BitBucket Cloud Git repos to GitHub.
The downside is that it won’t work for those who have self-hosted instances of your source control system (such as Azure DevOps Server or BitBucket Server) since these are likely not internet-facing. It also won’t migrate any pull request or issue metadata information.
This is usually what I do when migrating Git repos to GitHub, since it’s fast, efficient, and scriptable 😀. This migrates the entire repository, including all history, branches, and tags. The steps are as follows:
1 2 3 4 5 6 7 8 # Pre-requisite: Create repo in GitHub and grab the URL # migrate the repository git clone --mirror <source-repo-url> cd <source-repo-name> git push --mirror <github-repo-url> cd .. rm -rf <source-repo-name>
--mirror clones a bare copy of the repository that contains all refs (branches, tags, notes, etc.). With the bare copy of the repository, the files in the directory aren’t human readable, that’s why we clean up with the
rm -rf at the end. Run a
git clone <github-repo-url> to get a local copy of the repository and begin working with the repository in GitHub.
This of course works for transferring Git repos between any Git SCM.
A nice script that can do mass migrations is available here.
If your repository is already in GitHub, and you just need to move it to another user or organization, did you know you can simply transfer the repo?
Starting fresh might be best for repositories with very old history, and/or repositories with a lot of binaries committed. Here’s how this process might look:
- Create a new EMPTY repo in GitHub - don’t initialize with a README or .gitignore
- Get your latest changes in existing SCM; e.g.:
tf getto get latest changes
- Create a new folder and copy in the files from your existing repo - make sure to to NOT copy over the
- Initialize a new Git repo:
- Important: Add in a gitignore file - for .NET developers, you can run
dotnet new gitignore, alternatively see github/gitignore repo for other templates
- Delete any binaries or other files you don’t want committed to the new repo, and/or modify gitignore as needed
- Add the origin:
git remote add origin <github-repo-url>
git push -u origin main
Entirely scripted out, it would look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 cd old-repo # grab latest changes git pull # copy files to new folder and cd into it mkdir ./../new-repo && cp -r ./* ./../new-repo && cd ./../new-repo # initialize new git repo git init # add in and populate gitignore - either yourself or use `dotnet new gitignore` touch .gitignore # add in files, commit, and make sure we're using the main branch git add . git commit -m "Initial commit" git branch -M main # add remote and push git remote add origin <github-repo-url> git push -u origin main
- Perhaps the simplest is to use the Azure Repos Git repo importer to convert from TFVC to Git, and then migrate that repo to GitHub using Option 1 or Option 2 above
- If self-hosted, requires TFS 2017.2 or later
- Note that it can only migrate 180 days of history and only supports 1 branch
- For more advanced migrations, use the Git-TFS tool
See Microsoft’s documentation for more information on this topic.
Search GitHub and see what else is out there!
There is no shortage of options for migrating repositories, and while Git is certainly the easiest, there are still options for SVN, Mercurial, and TFVC out there.
I hope this post helps you find the right tool for your migration needs! 🥳