GitLab から GitHub へ移行してわかったことと、対応内容の記録
GitLab Premium を利用していた弊社が、GitHub Free(組織向け)へ移行した際の実際の手順や気づきをまとめました。
移行にあたって工夫したポイントや、両サービスを使ってみて感じた違いなど、実体験ベースでご紹介しています。
背景と目的
弊社では GitLab ブロンズプラン(月額 $4/ユーザー)を利用していましたが、プラン改定・価格改定 により、Premium プラン(月額 $29/ユーザー)へと推移しました。
これにより、年間数十万円のコスト増が発生しておりました。
一方 GitHub では、Free(組織向け)でもリポジトリ数無制限で CI/CD も 2,000 分まで利用可能と、基本的な機能をカバーしています。
Team プランでも $4/ユーザーとリーズナブルで、必要に応じて段階的に拡張が可能です。
このような背景を踏まえ、GitHub Free(組織向け)への移行を決定しました。
GitLab vs GitHub 機能比較表(2025/4/7 時点)
比較項目 | GitLab 特徴 | GitHub 特徴 |
---|---|---|
公式ドキュメントの和訳 | 英語が中心 | 主要なものは日本語対応あり |
リポジトリ管理 | グループ・サブグループでの階層管理が可能 | 単体リポジトリ中心。外部連携が豊富 |
ホスティング | セルフホスティングに加え、オンプレ運用も可能 | クラウド型(Enterprise Server あり) |
CI/CD 機能 | グローバル変数の簡易利用が可能 ($GITHUB_ENV相当の操作不要) GUIで環境変数の確認・管理が可能 |
テンプレートやMarketplaceが豊富 |
パッケージ管理 | グループ名をスコープ名にできる | パブリック公開ではストレージ・データ転送ともに無料・無制限 視覚的な統計情報 |
Issue・PRの操作性 | Issueからブランチ作成・MR発行がワンクリックで可能 | ブランチ作成やPR発行の操作がGitLabほど一体化されていない |
コメント機能 | Issue/MRでのスレッドコメントが標準対応 | PRコメントでもスレッド対応だが一部動作が異なることも |
セキュリティ管理 | シークレット値の直接参照に対応 | Dependabot による自動の脆弱性検出・アップデートが優秀 |
開発支援機能 | 専用の支援ツールは少なめ | GitHub Copilot によるAI補完支援が強力 |
再利用性・拡張性 | テンプレートや変数の再利用には設定が必要で、柔軟性はあるが自動化度は低め | Reusable Workflowsやマトリクスジョブなど、再利用性・拡張性が高い |
外部サービスとの連携 | 一部可能(Slack連携など) | Slack, Linear, Vercel, Sentry など多彩な連携が容易 |
OSSとの親和性 | 主にプライベートなプロジェクト向けとして利用される傾向が強い | OSS開発の中心的存在で、コミュニティが活発 |
移行方針と準備
-
移行対象の洗い出し
- ブランチ
- タグ
- メンバー
- 環境変数・シークレット
- CI/CD 設定(パイプラインスケジュール含む)
- Issue・マージリクエスト
- NPM パッケージ(スコープ・公開設定)
-
移行方法の検討
node-gitlab-2-github は以下のような課題がありました。
※移行ツール- 添付ファイルが移行できない
- Issue の作成者がツール実行者になる
- 元ユーザーが存在しない Issue は移行不可
※離任済みのユーザーを再招待する予定がない
そのため、以下のように決めました。
- Git リポジトリはミラーリングで対応する
- Issue・マージリクエストは GitLab の CSV エクスポート機能で残す
ダウンロードされた zip ファイルには、CSV には画像も含まれており、参照用途には十分でした。必要であれば復元や専用のビューアも作成可能です。
ミラーリングの手順
-
作業ディレクトリ構成
意図しない先に push を行わないよう下記ディレクトリの構成でリポジトリをクローンします。
├── gitlab # GitLab用:移行前確認(fetch/push: GitLab) ├── mirror # ミラーリング作業用(fetch: GitLab / push: GitHub) ├── github # GitHub作業用(fetch/push: GitHub)
-
GitHub 組織の作成
新しくアカウントを作成し、組織に切り替えます。
-
ミラーリング
ミラーリング作業用のディレクトリで下記手順を行います。
git clone --mirror <GitLabのURL> cd repo git remote set-url --push origin <GitHubのURL> git push --no-verify --mirror
以降の同期(任意)
git fetch -p origin git push --no-verify --mirror
-
デフォルトブランチの設定
GitHub ではデフォルトが
main
なので、必要に応じて変更してください。Team プラン以上では保護ブランチ設定なども行うと良いです。 -
環境変数の移行
GitLab 左メニュー → 設定 → CI/CD → 変数にある内容を GitHub に移行します。
CI/CD の移行
-
内容の把握
-
.gitlab-ci.yml
の有無 - 過去に稼働していたジョブ(左メニュー → ビルド → ジョブ)
- パイプラインスケジュールの有無(左メニュー → ビルド → パイプラインスケジュール)
-
-
.github/workflows/*.yml
への分割まとまったジョブ単位で GitHub Actions に分割して移行します。
プロジェクトのエクスポート
GitLab のエクスポート機能で CSV を出力。Issue、マージリクエスト、画像などが含まれます。Self-managed や Free プランでも利用可能です。
CI/CD 移行後の対応
- GitLab 側のパイプライン無効化
- GitHub 側での CI/CD 稼働開始
- 必要に応じたメンバー招待やチーム作成、アナウンス
運用上のTips(補足)
共通変数のワークフロー化。
再利用される側
name: Common Environment Variables
on:
workflow_call:
outputs:
ENV:
description: "環境識別子"
value: ${{ jobs.set-env.outputs.ENV }}
jobs:
set-env:
runs-on: ubuntu-latest
outputs:
ENV: ${{ steps.set-env.outputs.ENV }}
steps:
- id: set-env
run: |
case "${{ github.ref }}" in
"refs/heads/develop") ENV="DEV" ;;
"refs/heads/main") ENV="PROD" ;;
esac
echo "ENV=$ENV" >> "$GITHUB_OUTPUT"
呼び出し側
name: Deploy Workflow
on:
push:
branches:
- develop
- main
workflow_dispatch: # 手動実行:デバッグ用
jobs:
call-env:
uses: ./.github/workflows/env.yml
setup:
runs-on: ubuntu-latest
needs: call-env
env:
ENV: ${{ needs.call-env.outputs.ENV }}
outputs:
ENV: ${{ steps.set-env.outputs.ENV }}
PROJECT_ID: ${{ steps.set-env.outputs.PROJECT_ID }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set Environment Variables
id: set-env
run: |
# 他ジョブでも使用する環境変数をOUTPUTに設定
{
echo "ENV=$ENV"
echo "PROJECT_ID=acomo-$ACOMO_ENV"
} >> $GITHUB_OUTPUT
backend-migrate:
runs-on: ubuntu-latest
needs: setup
env:
ENV: ${{ needs.setup.outputs.ENV }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set Env
run: |
echo "ENV=$ENV"
echo "ENV=env.ENV"
echo "PROJECT_ID=${{ needs.setup.outputs.PROJECT_ID }}"
このように workflow_call を使って共通化を行うこともできます。
冗長になってしまうので、ベタで書いて見通しよくするか、再利用性を高めるかはケースバイケースです。
動的シークレット参照。
echo KEY_ENV=${{ secrets[format('KEY_{0}', ENV)] }}
echo KEY_ENV=${{ secrets[format('KEY_{0}', env.ENV)] }}
echo KEY_ENV=${{ secrets[format('KEY_{0}', needs.setup.outputs.ENV )] }}
このうち、2 行目(env.ENV を使ったもの)のみが有効です。
NPM レジストリへの公開。
- uses: actions/setup-node@v4
with:
node-version: '22.x'
registry-url: 'https://registry.npmjs.org/'
- name: コミットしてパッケージ公開:差分がある場合のみ
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN_ACOMO}}
run: |
# 将来的には、release-it に差し替えても良い
npm run client:patch
# acomo-clientのパッケージバージョンを更新するのでgitにコミットする
if [ -n "$(git status --porcelain)" ]; then # 変更差分チェック
git add acomo-client/package.json
# [skip ci]でCIの再実行を無効化
git commit -m "[skip ci] update acomo-client package version patch"
git push -f
# パッケージ公開(非公開の場合は課金が必要です)
npm publish --access public
fi
おわりに
GitHub への移行はコスト面では大きなメリットがありました。一方で、GitLab の機能の細やかさや管理のしやすさは、やはり組織規模や運用ポリシーによっては魅力的でもあります。
移行を検討されている方にとって、手順の参考、判断材料のひとつになれば幸いです。
Discussion