GitリポジトリをGitLabからGitHubへ移行する

当ブログのソースコードはGitLabで管理していたのですが、普段GitHubの方を使用することがほとんどなので、先日GitHubへ移行しました。
ソースコードのほかに、Issueやマジリクなどの移行できたので、その手順を残しておきます。

移行にあたって #

ミラーリングで対応できるもの #

  • ソースコード(+ コミット履歴)
  • ブランチ
  • タグ

これらはリポジトリのミラーリングを行うことで比較的すぐに移行できます。

これに加えてWikiについても、Wikiデータのミラーリングを行うことで対応できるようです。
※今回はWikiについては試してません。

移行スクリプトで対応できるもの #

以下のデータも移行したかったのですが、リポジトリのミラーリングでは対応していませんでした。

  • ラベル
  • マイルストーン
  • Issue
  • マジリク

しかし、有志の方がこれらのデータを移行するスクリプトを公開されていたので、今回はこちらを使わせていただきました。

移行スクリプトを使うための前提 #

  • Node.js 導入済み
  • npm か yarn コマンドが使えること

ちなみに移行元、移行先ともにプライベートリポジトリでも使用できました。

移行の仕様 #

移行スクリプトの 2020/08/08 時点での仕様です。

ラベル #

GitHubのデフォルトのラベルに、移行したラベルが追加されます。
色も同じっぽかったです。

また、gitlab merge requestというラベルも追加されます。
このラベルは、マジリクをIssue変換したものに付与されます。

マイルストーン #

タイトルや対象範囲、openかcloseなのかなど、ほぼそのまま移行されます。

Issue #

移行元
※すみません、移行元のスクショは撮り忘れました…。

移行先
移行先のGitHub Issue詳細画面

タイトルやコメント、openなのかcloseなのかなど、ほぼそのまま移行されます。
ただ、その作成日時は移行実施した日時になるため、コメントにIn GitLab by @h-yoshikawa0724 on Jun 28, 2020, 18:14のような、移行元での情報が記載されるようになっています。

画像アップロード内容まで移行されるかは未確認ですが、S3にアップロードするような設定もあるようです。

また、何らかの原因でIssue移行(移行先リポジトリにIssue作成)に失敗することがありますが、その救済設定(useReplacementIssuesForCreationFails)がデフォルトで有効になっています(移行スクリプトの設定ファイルも参照)。

自分の場合は、最初の頃、少し手伝ってもらっていた先輩が作ったIssueが移行時にエラーになっていました。
移行元と移行先ともにプライベートリポジトリであったこと、今は移行元リポジトリからも抜けていて、移行先リポジトリにいなかったことが、恐らくエラーの原因じゃないかと思います。

この設定が有効になっていると、以下のような代替Issueが作成されます。
移行元のIssueの説明が失われてしまいますが、その他の情報は引き継がれるようです。
移行先のGitHub (代替)Issue詳細画面

マジリク #

そのマジリクの状態に応じて、挙動が変わります。

  1. Open → プルリク(Open)に移行される?(今回、この状態のマジリクがなかったので未確認)
  2. Closed → プルリク(Closed)に移行される
  3. Merged + ブランチ削除済み → Issue(Closed)に変換される(gitlab merge requestのラベルがつく)
  4. Merged + ブランチあり → エラーで変換されない

こちらについても作成日時は移行実施した日時になるため、コメントにIn GitLab by @h-yoshikawa0724 on Jun 28, 2020, 18:14のような、移行元での情報が記載されます。

注意点としては、マージ済みの際の挙動でしょうか。
3については以下のような感じです。

移行元
移行元のGitLab マージ済みマジリク一覧画面

移行先
移行先のGitHub 変換されたクローズ済みIssue一覧画面

移行先のGitHub 変換されたクローズ済みIssue詳細画面

4については、マージ元のブランチはあるが、マージ先との差分がないためにエラーになってしまうようです。
何も移行が行われない問題がありますが、移行スクリプトの設定(useIssuesForAllMergeRequests)により、強制的に3と同じ挙動にすることで対応可能です(移行スクリプトの設定ファイルも参照)。

使用上限 #

README - import-limitに注意書きがあります。

この移行スクリプトでは、内部的にGitHub APIを使用しています。
このGitHub APIでは、1時間あたり5000 APIリクエストという制限があるため、移行内容が多いリポジトリだと上限に引っ掛かる可能性があることに注意です。

リポジトリ移行手順 #

前置きが長くなってしまいましたが、ここから実際の手順になります。

リポジトリの用意とミラーリング #

※補足
移行元 - GitLabリポジトリ:h-yoshikawa0724/changeofpace
移行先 - GitHubリポジトリ:h-yoshikawa0724/change-of-pace
として書いていっているので、適宜ご自分のリポジトリ情報に置き換えてください。


1.GitHubで移行先リポジトリを用意(作成するだけでOK)

2.移行元のベアリポジトリをクローン

$ git clone --mirror git@gitlab.com:h-yoshikawa0724/changeofpace.git

3.移行元のベアリポジトリを、移行先に反映

$ cd changeofpace.git

$ git push --no-verify --mirror git@github.com:h-yoshikawa0724/change-of-pace.git

この時点で、コード(コミット履歴)、ブランチ、タグは移行完了です。

なお、ベアリポジトリというのは作業ディレクトリを持たず、操作履歴などの情報のみを持つリポジトリのことを指すそうです。
末尾に.gitとつくのも特徴で、実際に配下ディレクトリを見ると以下のようになっていました。

$ ls changeofpace.git/
config  description  HEAD  hooks/  info/  objects/  packed-refs  refs/

アクセストークンの用意 #

GitLab #

プロフィールアイコンのSettings → Access Tokens. から。
apiread_repositoryのscopeを持ったトークンを生成し、その値を控えておきます。

GitLabでのアクセストークン設定画面

GitHub #

プロフィールアイコンのSettings → Developer settings → Personal access tokens. から。
「Generate new token」を押すと、アカウントのパスワード入力を求められるので入力。
repoのscopeを持ったトークンを生成し、その値を控えておきます。

GitHubでのアクセストークン設定画面

移行スクリプトの用意 #

1.移行スクリプトのダウンロード

$ git clone https://github.com/piceaTech/node-gitlab-2-github.git

2.ライブラリのインストール

$ cd node-gitlab-2-github

$ npm -i
or
$ yarn install

移行スクリプトの設定 #

設定ファイルの用意 #

1.src/settings.tsに以下を追記(useReplacementIssuesForCreationFails: boolean;の下にでも)

useIssuesForAllMergeRequests: boolean;

※最近追加された設定の型定義が漏れていたようです。これがないとスクリプトが動きません。
 ただ、自分がこの修正のプルリクを出したので、マージされるなり対応されたら、この手順は不要になります。
 → 2020/09/01追記 無事マージされました!

2.sample_settings.tssettings.tsにリネームして、設定を編集
自分の場合の例

import Settings from './src/settings';

export default {
  gitlab: {
    // url: 'https://gitlab.mycompany.com' // 公式でなく独自にホスティングしている場合のみ、そのURL
    token: 'XXXXXXXXXXXXX', // 先ほど控えたトークン
    projectId: 'XXXXXXX', // 後述参考
  },
  github: {
    // baseUrl: 'https://gitlab.mycompany.com:123/etc', // 公式でなく独自にホスティングしている場合のみ、そのURL
    owner: 'h-yoshikawa0724', // 移行先リポジトリのオーナーアカウントID
    token: 'XXXXXXXXXXXXX', // 先ほど控えたトークン
    repo: 'change-of-pace', // 移行先リポジトリ名
  },
  usermap: {
    'h-yoshikawa0724': 'h-yoshikawa0724', // GitLabアカウントID: GitHubアカウントID のマッピング(移行時にこれに応じて変換される)
  },
  projectmap: {
    'h-yoshikawa0724/changeofpace': 'h-yoshikawa0724/change-of-pace', // GitLabリポジトリ名: GitHubリポジトリ名
  },
  conversion: {
    useLowerCaseLabels: true,
  },
  debug: false, // デバッグ実行するかどうか
  usePlaceholderIssuesForMissingIssues: true, // 削除されたIssueがあった時などに、移行元と移行先とでその分Issue番号がずれるを防ぐために空のIssueを作成するか
  useReplacementIssuesForCreationFails: true, // 何らかの原因でIssue移行に失敗した際に、代替Issueを作成するか(移行元の説明は失われるが、それ以外は引き継がれる)
  useIssuesForAllMergeRequests: true, // 強制的に全ての移行元マジリクを移行先Issueに変換するか
  skipMatchingComments: [], // コメント移行をスキップするワード設定(このワードを含むコメントは移行されない、ワードの大文字小文字は区別しない)
  mergeRequests: {
    logFile: './merge-requests.json',
    log: false, // 移行元マジリクをlogFileに出力するかどうか(出力する場合は移行先へ移行されない)
  },
} as Settings;

設定の詳細や他の設定が知りたい場合は、README - Where to find info for the settings.tsに説明が記載されています。

プロジェクトIDの確認方法 #

GitLab のリポジトリトップ画面に表示されているので、そこで確認できます。

もしくは、一度projectIdnullにした状態で、このスクリプトを実行すると確認できます。
他の設定が問題なければ、リポジトリの一覧が表示されて、そこにプロジェクトIDが表示されるようになっています。

$ yarn start
yarn run v1.22.4
$ node node_modules/ts-node/dist/bin.js ./src/index.ts
XXXXXXX          change-of-pace         --



Select which project ID should be transported to github. Edit the settings.js accordingly. (gitlab.projectID)



Done in 14.89s.

移行スクリプトの実行 #

$ npm run start
or
$ yarn start

これで移行が開始されます。
当然、移行内容の量が多いほど時間がかかるので気長に待ちましょう。

Transfer complete!

と表示されたら移行完了です。
ちゃんと移行されているか確認してみましょう。

ちなみに自分の場合は、設定の関係上2回実行することになったのですが、基本的には前回の移行で作成された分と重複して移行(作成)されるということはないようです。

ログ出力を見た感じ、
ラベルやマイルストーンは「既に存在しています」
Issueやプルリクは「更新しました」
みたいな英語表示が出てたような気がします。

ただ、useReplacementIssuesForCreationFails設定により作られた代替Issue(Issueタイトル末尾に[REPLACEMENT ISSUE]がついているもの)に関しては、既に存在すると認識されないようで、重複して作られてしまいました。

その他の設定移行 #

必要に応じて、その他の設定も移行しましょう。
自分の場合は、移行元リポジトリとNetlifyを連携させていたので、移行先リポジトリで連携しなおしました。

Netlify #

Settings → Build & Deploy → Continuous Deployment → Build settings → 「Edit settings」
から、連携するリポジトリを更新。

後処理 #

これもまた必要に応じて行いましょう。

  • 旧GitLabリポジトリの削除
  • ミラーリング時にローカルに作った、ベアリポジトリの削除
  • 今回移行したプロジェクトのローカルリポジトリのリモートURLを、移行先リポジトリの方に設定
  • アクセストークンを削除

今回、特に大きな問題もなくリポジトリの移行ができて安心しました。

この移行スクリプトを作成された方に感謝ですね!
使い方をちゃんと理解したうえで使用すれば、とても便利なスクリプトなので、移行を考えられている方はぜひ使ってみてはいかがでしょうか。

ではでは。

参考リンクまとめ #