BitbucketからGitLabへ移行しよう! — 機能比較と移行手順を徹底解説
はじめに
「今のソースコード管理ツール、なんかしっくりこない…」「CI/CDやプロジェクト管理も一元化したい」そんな気持ちを抱えているエンジニアは少なくないはずです。
本記事では、BitbucketからGitLabへ移行する方法を、公式ドキュメントをベースに実践的にまとめました。移行先として GitLab を選んだ理由から、具体的な手順・注意点まで網羅しています。
なぜ GitLab なのか
GitLab は単なるGitホスティングサービスではありません。
- リポジトリ管理
- CI/CD パイプライン(GitLab CI)
- イシュートラッカー
- コードレビュー(マージリクエスト)
- セキュリティスキャン
- パッケージレジストリ
- Wiki・ドキュメント管理
これら全てが一つのプラットフォームで完結します。
Bitbucket + Jira + Jenkins のような複数ツールを組み合わせている場合、GitLab への移行でツールチェーンをシンプルに統合できます。
移行パターンは2種類
GitLab への移行は、移行元によって手順が異なります。
| 移行元 | 方法 |
|---|---|
| Bitbucket Cloud (bitbucket.org) | Bitbucket Cloud インポーター |
| Bitbucket Server (オンプレミス) | Bitbucket Server インポーター |
それぞれ解説します。
Bitbucket Cloud からの移行
対応バージョン
- GitLab Free / Premium / Ultimate
- GitLab.com / Self-Managed / Dedicated
インポートできるもの
| 項目 | インポート可否 |
|---|---|
| リポジトリの説明 | 可 |
| Git リポジトリデータ | 可 |
| Issue(コメント含む) | 可 |
| プルリクエスト(コメント含む) | 可 |
| マイルストーン | 可 |
| Wiki | 可 |
| ラベル | 可 |
| LFS オブジェクト | 可 |
| プルリクエストの承認 | 不可 |
| 承認ルール | 不可 |
プルリクエストの承認履歴は引き継げない点に注意してください。
インポート時の動作詳細
リポジトリ全般:
- Bitbucket Cloud で private なリポジトリは GitLab でも private として作成されます(公開設定が引き継がれます)
- PR と Issue への参照番号は保持されます
- 存在しない名前空間(グループ)は自動的に作成されます。名前空間がすでに使用中の場合は、インポート実行者の名前空間下にインポートされます
Issue・プルリクエスト・コメントのインポート時:
- Bitbucket のニックネームをもとに GitLab ユーザーを検索し、一致するユーザーを著者・アサイニーとして設定します
- 一致するユーザーが見つからない場合は、プロジェクト作成者(インポート実行者)が著者となり、元の Bitbucket 著者への参照がコメントに残されます
プルリクエスト固有の動作:
- ソース SHA を使用し、リポジトリに存在しない場合はマージコミット SHA にフォールバックします
- マージリクエストのアサイニーは著者に設定され、レビュアーは Bitbucket の identities と一致する GitLab ユーザーに設定されます
- GitLab 側のステータスは
opened/closed/mergedの3種に変換されます
Issue 固有の動作:
- Bitbucket の Issue タイプに対応するラベルが付与されます(
bug/enhancement/proposal/task) - Bitbucket で
resolved/invalid/duplicate/wontfix/closedになっている Issue は GitLab でも close されます
前提条件
- Bitbucket Cloud インテグレーションが有効であること(GitLab.com ではデフォルト有効、Self-Managed では管理者による有効化が必要)
- Bitbucket Cloud インポートソースが有効であること(GitLab.com ではデフォルト有効、Self-Managed では管理者による有効化が必要)
- インポート先グループで Maintainer または Owner ロール が必要(GitLab 16.0 以降)
- インポート元のプルリクエストはフォークではなく同一プロジェクト内であること(フォークからのPRは空のマージリクエストになります)
ユーザーマッピングの前準備
インポート後にコントリビューションが正しいユーザーに紐づくよう、事前に以下を確認してください。
- Bitbucket アカウント設定 のユーザー名と、Atlassian アカウント設定 の表示名が一致していること
- GitLab プロフィールのサービスサインイン で Bitbucket アカウントを連携済みであること
この手順を事前に踏まずにインポートすると、コントリビューションがインポート実行者のアカウントに統一されてしまいます。
Bitbucket Cloud API トークンの生成
Import API を使う場合、Bitbucket Cloud の API トークンが必要です。なお、従来のアプリパスワードは GitLab 18.9 で非推奨となり、GitLab 19.0 で削除されました。現在は API トークンを使用してください。
- https://id.atlassian.com/manage-profile/security/api-tokens へアクセス
- 「スコープ付き API トークンを作成」を選択
- トークン名・有効期限を入力して次へ
- 「Bitbucket」を選択して次へ
- 以下のスコープを最低限付与する:
read:repository:bitbucketread:pullrequest:bitbucketread:issue:bitbucketread:wiki:bitbucket
- 「トークンを作成」してコピー
インポート手順
- GitLab にサインイン
- 右上の「新規作成」から「新しいプロジェクト/リポジトリ」を選択
- 「プロジェクトをインポート」を選択
- 「Bitbucket Cloud」を選択
- Bitbucket にサインインしてアクセスを許可
- インポートするプロジェクトを選択(名前でフィルタリング可能)
- 「インポート」をクリック
再インポートする場合は「再インポート」を選択し、新しい名前を指定します(再インポートは新しいコピーとして作成されます)。
Bitbucket Server からの移行
対応バージョン
- GitLab Free / Premium / Ultimate
- GitLab.com / Self-Managed / Dedicated
インポートできるもの
Bitbucket Server からのインポートでは、リポジトリの説明、Git リポジトリデータ、コメント・ユーザーメンション・レビュアー・マージイベントを含むプルリクエスト、LFS オブジェクト、コードへのコメント、スレッド、プロジェクトフィルターがインポート対象です。
| 項目 | インポート可否 | 備考 |
|---|---|---|
| リポジトリの説明 | 可 | |
| Git リポジトリデータ | 可 | |
| プルリクエスト(コメント・メンション・レビュアー・マージイベント含む) | 可 | |
| LFS オブジェクト | 可 | |
| コードへのコメント | 可 | ※1 |
| スレッド | 可 | ※2 |
| プロジェクトフィルター | 可 | ※3 |
| Markdown 内添付ファイル | 不可 | |
| タスクリスト | 不可 | |
| 絵文字リアクション | 不可 | |
| プルリクエスト承認 | 不可 | |
| プルリクエストの承認ルール | 不可 |
- ※1: GitLab はコードの任意行へのコメントを許可していないため、範囲外のコメントはマージリクエストのコメントとして挿入されます
- ※2: 複数階層のスレッドは1スレッドに折りたたまれ、引用が元コメントに追加されます
- ※3: プロジェクトフィルターはあいまい検索非対応で「前方一致」または「完全一致」のみ対応
インポート時の動作詳細
- Bitbucket Server で private なリポジトリは GitLab でも private として作成されます(公開設定が引き継がれます)
- 存在しない名前空間(グループ)は自動的に作成されます。名前空間がすでに使用中の場合は、インポート実行者の名前空間下にインポートされます
- インポートされたマージリクエストとコメントには GitLab 上で「インポート済み」バッジが表示されます(GitLab 17.2 以降)
前提条件
- Bitbucket Server は GitLab インスタンスからアクセスできる必要があります。Bitbucket Server の URL がパブリックに解決可能か、GitLab が稼働しているネットワーク上でアクセス可能である必要があります。
- GitLab 管理者による Bitbucket Server インポートソースの有効化が必要(GitLab.com ではデフォルト有効)
- インポート先グループで Maintainer または Owner ロール が必要(GitLab 16.0 以降)
- 管理者アクセス権を持つ Bitbucket Server 認証トークンが必要です。管理者アクセス権がない場合、一部のデータはインポートされません。
クローズ・マージ済み PR のコミット取得について
クローズまたはマージ済みのプルリクエストをインポートする際、リポジトリに存在しないコミット SHA は Bitbucket Server から自動フェッチされます。
- ソースコミットの SHA は
refs/merge-requests/<iid>/head形式で保存 - ターゲットコミットの SHA は
refs/keep-around/<SHA>形式で保存
ソースコミットがリポジトリに存在しない場合は、コミットメッセージに SHA を含む代替コミットが使用されます。
インポート時間の目安
以下の規模のプロジェクトは、インポートに約8時間かかると見込まれます:プルリクエスト13,000件、タグ7,000件、リポジトリサイズ500GiB。
大規模リポジトリの場合は、メンテナンスウィンドウを設けてインポートを計画することをおすすめします。
インポート手順
- GitLab にサインイン
- 右上の「新規作成」から「新しいプロジェクト/リポジトリ」を選択
- 「プロジェクトをインポート」を選択
- 「Bitbucket Server」を選択
- Bitbucket にサインインしてアクセスを許可
- インポートするプロジェクトを選択(名前でフィルタリング可能、名前空間も指定可)
- 「インポート」をクリック
再インポートする場合は「再インポート」を選択し、新しい名前を指定します(GitLab 15.9 以降対応。再インポートは新しいコピーとして作成されます)。
代替マッピング方式について(非推奨・Server のみ)
bitbucket_server_user_mapping feature flag を無効化することで、代替のユーザーマッピング方式を使用できます。ただし以下の制限があります。
- GitLab.com では使用不可(ポストマイグレーション方式のみ対応)
- この方式で見つかった問題は修正される見込みがないため、基本的にはポストマイグレーション方式の使用を推奨します
代替方式では、Bitbucket Server ユーザーのメールアドレスを GitLab のユーザーデータベースと照合します。一致するユーザーが見つからない場合はプロジェクト作成者が代わりに使用され、コメントに元の作成者の注記が追加されます。プルリクエストのレビュアーや承認者は割り当てられません。
プルリクエストの説明やコメント内のメンションも同様にメールアドレスで照合されます。GitLab ユーザーが見つからない場合、そのメンションは静的テキストとして残ります。
ユーザーがマッチするには、対象の GitLab ユーザーがそのプロジェクトへの読み取り以上のアクセス権を持っている必要があります。パブリックプロジェクトの場合は、プロジェクトに招待されているユーザーのみマッチします。
ユーザーマッピングについて(GitLab 17.8 以降)
GitLab 17.8 以降、GitLab.com および GitLab Self-Managed ではポストマイグレーションユーザーマッピングが有効になっています。
これにより、インポート完了後にコントリビューションと既存 GitLab ユーザーを紐づけることができます。Bitbucket 側のユーザーとメールアドレスが一致する GitLab ユーザーが自動的にマッピングされます。
マッピング変更履歴(Bitbucket Server・バージョン別)
以下は主に Bitbucket Server インポートに関するマッピング変更履歴です。
| バージョン | 変更内容 |
|---|---|
| GitLab 13.4 | メールアドレスまたはユーザー名によるユーザーマッピング追加(フラグ付き、Server) |
| GitLab 16.3 | レビュアーのインポート対応(Server) |
| GitLab 16.6 | Bitbucket Cloud の並列インポート対応(フラグ付き、Cloud) |
| GitLab 16.7 | PR 承認のインポート対応(Server) / Bitbucket Cloud の並列インポートが GA(Cloud) |
| GitLab 16.8 | ユーザーメンションの GitLab ユーザーへのマッピング追加(Server) |
| GitLab 17.1 | メールアドレスのみによるユーザーマッピングに変更(Server) |
| GitLab 17.2 | インポート済みアイテムへの「インポート済み」バッジ表示(Cloud・Server 共通) |
| GitLab 17.8 | ポストマイグレーションユーザーマッピングが GitLab.com・Self-Managed で有効化(Cloud・Server 共通) |
インポート済みアイテムの識別(GitLab 17.2 以降)
GitLab 17.2 以降、一部のインポートされたアイテムには「インポート済み」バッジが表示されます。これにより、インポートされたコンテンツとネイティブに作成されたコンテンツを区別しやすくなっています。
トラブルシューティング
GUI インポートが動かない場合
- Import API の Bitbucket Server エンドポイントを利用する
- リポジトリミラーリング を設定する(詳細なエラーログが確認できます)
なお、Bitbucket Server インポートで解決しない問題は、Bitbucket Cloud のトラブルシューティングも参考になる場合があります。
インポートに間違ったアカウントを使ってしまった場合(Cloud)
誤ったアカウントでインポートを開始してしまった場合は、以下の手順で対処してください。
- GitLab の Bitbucket アクセスを取り消す(インポート時に許可したアクセスの逆操作)
- 正しい Bitbucket アカウントでサインインし直して再度インポートを実行する
名前が一致しているのにユーザーマッピングが失敗する場合(Cloud)
ユーザーマッピングが機能するには、Bitbucket のユーザー名と Atlassian の表示名が一致している必要があります。名前が一致しているにもかかわらず失敗する場合は、GitLab データベース内の Bitbucket 外部 UID が現在の Bitbucket 公開名と一致していない可能性があります。
以下の手順で確認・修正してください。
- API で認証済みユーザー情報を取得する
- レスポンスの
identities属性に含まれるextern_uidが現在の Bitbucket 公開名と一致しているか確認する - 不一致の場合は GitLab プロフィールのサービスサインイン で Bitbucket アカウントを再連携する
- 再連携後、API で再度
extern_uidが正しく更新されたか確認する - インポートしたプロジェクトを削除し、再インポートする
LFS オブジェクトがインポートされない
特殊文字を含むパスワードや個人アクセストークンを使用している場合、LFS オブジェクトがダウンロードやクローンできないことがあります。その場合はトークンを再生成してください。
インポートURLがブロックされる
「Import URL is blocked」のようなエラーでインポートが失敗する場合、Bitbucket Server またはリバースプロキシが正しく構成されていない可能性があります。
Projects API で新規作成されたプロジェクトの import_url を確認し、そのURLが外部から解決可能かチェックしてください。Bitbucket Server がプロキシサーバーを認識していることを確認してください。プロキシサーバーは Bitbucket が URL を構築・使用する方法に影響を与える可能性があります。
JSON::NestingError でインポートが失敗する
「JSON::NestingError」を含むエラーでインポートが失敗する場合、Bitbucket Server のレスポンスに max_http_response_json_depth 設定を超える深くネストされたオブジェクトが含まれています。GitLab 管理者に依頼して、この上限値を引き上げてもらってください。
GitLab をもっと使いこなすために
移行が完了したら、GitLab の真価を発揮させましょう。
まず試してほしい機能
GitLab CI/CD
.gitlab-ci.yml をリポジトリに置くだけで CI/CD パイプラインが動きます。Jenkins や CircleCI を別途管理する必要がなくなります。
マージリクエスト
コードレビューはもちろん、レビュアーのアサイン、承認ルール、マージ条件の設定まで細かく制御できます。
GitLab Pages
静的サイトを GitLab CI 経由で簡単にデプロイできます。ドキュメントサイトの公開に便利です。
Container Registry
Docker イメージをそのままプロジェクトに紐づけて管理できます。
Sidekiq のチューニング(Self-Managed の場合)
大規模インポートをスムーズに行うには、Sidekiq の設定チューニングが有効です。
まとめ
| 観点 | Bitbucket Cloud | Bitbucket Server |
|---|---|---|
| インポート難易度 | 低(OAuth 連携で完結) | 中(管理者トークン必要) |
| 所要時間 | 数分〜数時間 | 規模によっては8時間超 |
| ユーザーマッピング | ポストマイグレーション対応(17.8〜)+事前の Bitbucket アカウント連携が必要 | ポストマイグレーション対応(17.8〜) |
| 承認履歴の移行 | 不可 | 不可 |
GitLab への移行は、単なるリポジトリ移転ではなく、開発ワークフロー全体を見直す絶好の機会です。CI/CD・セキュリティスキャン・プロジェクト管理を一元化し、開発体験を大きく改善できます。
ぜひこの機会に GitLab を使いこなして、チームの生産性を一段階引き上げてみてください。