This guide covers migrating a github repository from one github location to another (most likely Github Enterprise <-> Github.com). Migrating just the git repository is the easy part. The hard part is migrating pull requests, issues and comments. And it is even more difficult if you're moving from Github Enterprise to Github.com and your repository size is over the 1GB limit and requires history re-writing to get the size down.
Before we start, I'd like to credit Michael Welch for creating a guide at https://github.com/michaelgwelch/migrate-issues. I rewrote all new code following his guide and source code. I modernized the source, cleaned up and made new messes, added support to resume most longer steps, added support for history re-writing, got a bit more aggressive with preserving comments on force-pushed pull request branches and migrating images in issues and comments. I learned a lot more about github than I ever thought I would.
It is best to do this process when nobody is currently working. All in-progress work should be pushed to the source remote repository before starting. Any work pushed during this process or not pushed prior to starting will be lost and patches will have to be created to apply to the new repository. For smaller repos, this could be done at night. Larger you may need to do it over the weekend (copying comments can take a while with rate limits).
Prep Steps:
dependabot security updates
enabled, you will need to disable it before pushing your new repo. Otherwise, if it picks up a new vulnerability it will auto-create a PR and your issue numbers will no longer matchconfig.js
and s3Config.js
files created during initialization
(see steps below)Migration Steps:
npm install
npm run initialize
- this will create a config.js
file. Modify this file. The token here will dictate the user that creates comments and pull requests. You might want this to be a non-user account (maybe automation account) to make it obvious you personally didn't create all issues, pull requests and comments. The scripts will have an author section to credit the real authorusers.js
s3Config.js
accessKeyId
, secretAccessKey
, and region
npm run test:s3
to test your S3 connection and make sure the given bucket in config.js
existsnpm run test:source
. This will test your source configuration. Adjust the source config until this worksnpm run test:target
. This will test your target configuration. Adjust the source config until this worksgit clone <source-repo-url> --mirror
. This will clone your source repo. The mirror
option will download all branches, tags and refs (required for converting pull requests)npm run fetch
. This will download all github artifacts. Note will count toward your API limit, but fetching is in batches of 100. This won't be much for small repos, but a repo with 13K commits would be 100s of requestsnpm run rewriteRefs
. This is important for copying pull requests. Github uses hidden refs for pull request branches (that even persist after you PR branch is deleted), but github will reject pushing hidden refs. Rewriting them means they will show as actual branches in your new repository, but we'll clean them up later.npm run checkSize
. See how big your repo isnpm run bfg
. This will download the BFG jarjava -jar bfg-1.13.0.jar --strip-blobs-bigger-than 2M <repo>.git
(cd <repo>.git; git reflog expire --expire=now --all && git gc --prune=now --aggressive)
. NOTE change <repo>
to the target repository name.npm run checkSize
. This is how big the target repo will benpm run rewrite
. This will use the commit map created by BFG and write the new commit hashes to all downloaded pull requests, comments and commits. This can take a while depending on how many pull requests and comments you have. Each step has progress logging to help.cd <source-repo>.git
git push <dest-repo> --mirror
. This will push all branches, tags and refs to the target destinationnpm run createBranches
. This will create a branch for each PR on the target repository. This is the first step that pushes github artifacts to the destination reponpm run createIssues
. This will create issues and pull requests using base and head branches. State tracking is used in case of any errors. This step is the most finicky because the issues must be added in order, so the script will bail on any error informing you how to proceed. You may need to create a dummy issue to move on.npm run createComments
. This will create all comments downloaded from the source repository. This step will probably take the longest. This step uses throttling to try to stay under your API rate limit set by github. This will also log a lot. State tracking is used here as well, so you can quit and pick up later.npm run updateIssues
. This will close all issues that are closed in the source repository. This will also add all the previous labels and add the "Github Import" label. We can't tell Github the PRs are merged, only closed.npm run deleteBranches
. This will clean up all the base and head branches created by the migration processnpm run createReleases
. This will create all the releases downloaded from the source repository.If you've already migrated and started creating new issues / pull requests, you can still migrate from your original repository.
OriginalRepo -> NewRepo1
... some period of time ...
OriginalRepo -> NewRepo2
NewRepo1 -> offset issues -> NewRepo2
To migrate NewRepo1
to NewRepo2
, before running git push
and createBranches
, first update config.js
to have an increment, based on the last issue # from OriginalRepo
:
increment: 188
Then, run npm run increment
. After that, you can run through git push
, createBranches
, createIssues
, and createComments
.
The pull requests to NewRepo1
that merged will have mismatched #'s, so you'll need to manually rewrite commit messages to link up the numbers (same as the offset / increment).