GitLabからGitHubへリポジトリを移行しました


開発グループの石川です。
ファーエンドテクノロジーでは、GitLabでリポジトリの管理を行っていましたが、昨年の12月にGitHubでの管理に変更しました。移行の際には考慮漏れも多く結構苦戦したので、同じように移行する方の参考になれば良いかないうことで共有します。

移行対象のリポジトリは100以上あり、手作業での移行は大変なのでGitLabやGitHubのAPIを使って進めました。APIを利用するために書いたスクリプトについても公開できれば良かったのですが、少し前に書いたスクリプトで現在も利用できる状態かわからないため今回はざっくりとした説明のみにしています。

流れに沿って移行の様子を振り返り

1. 移行したいリポジトリを調査

GitLabを使っていて管理しているリポジトリの中には不要になったリポジトリや検証用のリポジトリもあったため、事前に移行したいリポジトリを調査しました。また、この時にマージリクエストの移行が必要かも調べ、マージリクエスト上のレビューのやりとりが知見として大きいということで一部のリポジトリについてはマージリクエストも移行することになりました。

2. GitHubに空リポジトリを作成し、GitLabのRepository mirroring機能を使ってGitLabからミラーするように設定

リポジトリの移行については、GitLabのRepository mirroring機能を利用し、次の処理をリポジトリ単位で何度も繰り返し実行することでリポジトリの移行を行いました。ミラーすることで、GitLabを利用した業務を止めないままにGitHubへのリポジトリ移行を進めることができます。

  1. GitHubのOrganizationにGitLabと同じ名前で空リポジトリを作成
  2. GitLabのCreate a push mirror APIを使ってGitHubに作った空リポジトリにミラーする設定を追加
  3. 数秒sleep

しかし、終わってから考えてみると、GitLabの利用を一時的に止めて各リポジトリをgit cloneで取得してGitHubにgit pushするやり方の方が良かったかもと思っています。

GitLabのRepository mirroring機能について、ミラー設定はAPIで追加できるのですが、同期のトリガーは「git push」か「手動でボタンを押す」の二つしか無くAPIからはトリガーできません。ミラー設定をしてから1週間くらいは置いたためその間にpushがあったリポジトリについてはGitHubに自動で移行できたのですが、アクティブに動いていないリポジトリについては「手動でボタンを押す」必要があり、それが想定以上に大変でした。(同期ができていないリポジトリを絞り込むため、API(List organization repositories)を使ってOrganizationのリポジトリ一覧を取得し、その中からsizeが0のリポジトリのみに絞り込んで対応しました。)

使ったAPI

3. 同期したGitHub側のリポジトリでデフォルトブランチがおかしくなる問題が発生したため対応

GitHubへのミラー設定後、同期できたGitHub側のリポジトリでデフォルトブランチがおかしくなる問題が発生しました。

原因

空リポジトリを作ったときにデフォルトブランチはmainで作られていましたが、GitLabにあるリポジトリのほとんどがmasterブランチをデフォルトとしていてmainブランチが存在しませんでした。GitHubがデフォルトとして設定されているmainブランチを探しても見つからなかったために他のブランチがデフォルトとして表示されてしまっていました。

対応

masterからmainへのブランチ名変更を急にやると問題が起きかねないので、GitHub側のデフォルトブランチ設定をmainからmasterに変えるように変更しました(Update repository APIでdefault_branchをmasterに変更)。移行後に新しく作ったリポジトリのデフォルトブランチは、特に理由が無ければmainにしています。

使ったAPI

4. アクセス権限の設定

仕事内容に応じたTeamに所属するように設定し、そのTeamを各リポジトリに割り当てました。リポジトリ件数が多かったので、これも権限のリストを元に自作スクリプトによって一気に設定しました。

使ったAPI

5. 社内でGitHubの移行説明会を実施

git remoteがGitLabのリポジトリになっているのをGitHubのリポジトリに変更する作業は、説明会を開いて一気にやってもらいました。コマンドの実行でうまくいかないところがあっても、同時に作業することで周りのうまくいっている人や詳しい人に聞きやすく、大きな問題無く設定変更を行うことができました。

6. 原則GitHubの利用に切り替え

説明会終了後に自社サーバーで動かしていたGitLabにIPアドレス制限をかけ、原則GitHubを使って業務を行うように切り替えました。

7. GitLabのRepository mirroring機能を使って同期していた処理をGitHub Actionsで置き換え

2. GitHubに空リポジトリを作成し、GitLabのRepository mirroring機能を使ってGitLabからミラーするように設定 の手順でもRepository mirroring機能を利用しましたが、デプロイの自動化などをこの機能をトリガーに実現している物がいくつかあったため、GitHub Actionsで置き換えました。 GitLabのようにGUI上だけでは設定できませんが、一度コードを書いてしまえば他のリポジトリに対しても一部書き換えるだけで流用できたと思います。

GitHubの移行に切り替えてから対応の必要性に気づいたので、事前に洗い出せなかったという点は反省ポイントです。

8. マージリクエストの移行

マージリクエストの移行には、API経由でマージリクエストやIssueの移行を行うためのスクリプトが公開されていたため、それを利用させていただきました。
https://github.com/piceaTech/node-gitlab-2-github

node-gitlab-2-githubではsettings.tsにリポジトリの情報を書いた上で npm run start を実行するとそのリポジトリのマージリクエストなど指定した情報をGitLabからGitHubに移行できるというものです。

GitLabではすでにマージした作業用ブランチはほとんど削除していたため、useIssuesForAllMergeRequests設定を有効にしてマージリクエストをGitHubのIssueとして移行しました(ブランチが残っていないとプルリクエストとしての移行ができないため)。issueに移行した分多少見やすさは落ちますが、コードに対してのコメントはどの行へのコメントが分かるようになっていたりと良くできているので、後から変更の経緯や情報を探す分には問題ありません。


マージリクエストを移行したissueの様子(例)

node-gitlab-2-githubではリポジトリ1つずつしか移行ができないのですが、一気に実行してしまいたかったため

  1. settings.tsを書き換え
  2. npm run start で移行を実行
  3. 数秒sleep

という処理をリポジトリ単位で何度も繰り返し実行するスクリプトを書き、cronで深夜に動くようにして実行しました。一気に実行しすぎるとGitHubにリクエストを弾かれるため、sleepは結構多めに取りました。

マージリクエストの移行で失敗した点

マージリクエストの移行では、GitHubのリポジトリのIssueにたくさんのコメントが追加されるため、1つのリポジトリを移行しただけでも数千単位の通知メールが発行されることになります。マージリクエストの移行よりも先にGitHubでの運用を始めてしまっていたためにリポジトリに変更を加えるとそのリポジトリをウォッチしているユーザーに大量の通知が届く可能性があり、それを避ける方法が無いかいろいろ検証が必要になりました。

結局「GitHubですべてのメール通知を一時的にオフにする」か「マージリクエスト移行対象のwatchを外す」という対応を利用者全員に依頼することになり、手間をかけることになってしまいました。

=> 4. アクセス権限の設定 よりも先にマージリクエストの移行を行っていれば、この問題は回避できるはずです。

9. GitLabの利用を停止

マージリクエストの移行が完了したのを確認してから、GitLabへのアクセスを停止しました。GitHubへ運用を移してから一定期間はGitLabにもアクセスできるようにしていたことで、必要なデータを失うといったトラブルもなく移行が無事完了しました。

移行をした感想

GitLab・GitHubともにAPIが充実しているため、やりたいことのほとんどをコード化できたのは良かったです。手作業でやるのと違って作業漏れなどを防げますし、100以上のリポジトリに対してもあまり時間をかけずに移行することができました。失敗した点なども含めて、GitLabからGitHubへの移行を考えている方の参考になれば幸いです。


移行に使ったスクリプトたち
My Redmine

こちらの記事もオススメです!
チームで共通のフックスクリプト(Git hook)を使っています
Gitでバージョン管理されたスクリプトをフックスクリプトとして実行するために core.hooksPath の設定を利用しています。
Redmineのバグを見つけて改善できた話
会社で使っているRedmineでバグを発見。Redmineの改善につなげるため気がついたことを共有しています。
RedMica 2.1(Redmine 5.0互換)と Azure AD で SAML認証 をする方法
RedMica stable-2.1(Redmine 5.0互換)でSAML認証する方法。
Rails7.0にアプリケーションをアップデートしています
社内で開発中のRuby on RailsアプリケーションをVer6.1系からVer7.0系にアップデートした手順の一部をご紹介します。
AWS マネジメントコンソールへのログイン通知(2022年版)
証跡をマルチリージョン対応し他のサービスを連携して比較的簡単に対応ができました。
ファーエンドテクノロジーからのお知らせ(2022/08/17更新)
My Redmine 無料個別相談会in東京(9月9日)を開催します(3組限定)
My Redmine 無料個別相談会を9月9日(金)に東京で開催します。3組限定。お客様の疑問・課題を講師が一緒に解決します。
「FAR END NEWS」2022年第3号 発行
広報紙「FAR END NEWS」2022年第1号を発行しました。弊社サービスの運用・サポートに携わっているスタッフや弊社の取り組みをご紹介します。
【My Redmine導入事例】製造業の株式会社イシダテックにおける活用事例を公開 業務状況の可視化により社内リソースの有効活用が可能に
My Redmineの導入と業務改善の推進で案件の情報共有に成功。鮮度・解像度が低かったプロジェクトの全体像が明確に。製造業の企業が取り組んだ工夫は、導入推進のための体制づくりや社内へのサポート。
プロジェクト管理ツール「RedMica」バージョン 2.1.0をリリース Redmine互換のオープンソースソフトウェア
今日使える明日のRedmine「RedMica」の最新バージョン2.1.0をリリースしました。次期バージョン Redmine 5.1の新機能を先行利用できます。
Redmineの最新情報をメールでお知らせする「Redmine News」配信中
新バージョンやセキュリティ修正のリリース情報、そのほか最新情報を迅速にお届け