- 概要
- ユースケース
- リモートリポジトリへのプッシュ
- GitLabからGitHubへのプッシュミラーの設定
- 2FAを有効にしたGitLabインスタンスへのプッシュミラーの設定
- リモートリポジトリからのプル
- 強制更新
- 双方向ミラーリング
- トラブルシューティング
リポジトリのミラーリング
リポジトリミラーリングは、外部ソースとの間でリポジトリのミラーリングを可能にします。 ブランチ、タグ、コミットをリポジトリ間でミラーリングするために使用できます。
GitLabのリポジトリミラーは自動的に更新されます。 手動で最大5分ごとに更新をトリガーすることもできます。
概要
リポジトリのミラーリングは、GitLab以外のリポジトリを使いたいときに便利です。
GitLabがサポートするリポジトリのミラーリングには2種類あります:
- Push: GitLabリポジトリを別の場所にミラーリングします。
- Pull: リポジトリを別の場所からGitLabにミラーリングします。
ミラーリポジトリが更新されると、すべての新しいブランチ、タグ、コミットがプロジェクトのアクティビティフィードに表示されます。
少なくともプロジェクトに開発者アクセス権を持つユーザーは、即時アップデートを強制することもできます:
- ミラーはすでに更新されています。
- 前回の更新から5分経過していません。
セキュリティ上の理由から、GitLab 12.10 以降では、オリジナルのリポジトリへの URL は、ミラーリングしたプロジェクトのメンテナー権限またはオーナー権限を持つユーザーにのみ表示されます。
ユースケース
以下は、リポジトリミラーリングの使用例です:
- GitLabに移行したものの、まだプロジェクトを別のソースに残しておく必要がある場合、GitLabへのミラーリング(プル)を設定するだけで、コミット、タグ、ブランチなどの重要な履歴がすべてGitLabインスタンスで利用できるようになります。
- 別のソースに古いプロジェクトがあり、もうアクティブに使っていないけれどもアーカイブのために削除したくない場合。 その場合、プッシュミラーを作成することで、アクティブなGitLabリポジトリが古い場所に変更をプッシュすることができます。
リモートリポジトリへのプッシュ
既存のプロジェクトでは、以下のようにプッシュ・ミラーリングを設定できます:
- プロジェクトの[Settings(設定)]>[Repository(リポジトリ)]に移動し、[Mirroring repositories(リポジトリのミラーリング)]セクションを展開します。
- リポジトリのURLを入力します。
- Mirror directionドロップダウンからPushを選択します。
- 必要に応じて、認証方法ドロップダウンから認証方法を選択します。
- 必要に応じて、[ミラー保護ブランチのみ] ボックスをオンにします。
- 必要であれば、Keep divergent refsボックスにチェックを入れてください。
- Mirrorrepository ボタンをクリックして、設定を保存します。
プッシュミラーリングが有効になっている場合、ミラーの分岐を防ぐために、ミラーリポジトリに直接コミットのみをプッシュします。 すべての変更は、いつでもミラーリポジトリに反映されます:
- コミットはGitLabにプッシュされます。
- 強制アップデートが開始されます。
リポジトリ内のファイルにプッシュされた変更は、少なくともリモートミラーに自動的にプッシュされます:
- 受信から5分以内。
- ミラー保護ブランチのみが有効な場合は1分以内。
ブランチが分岐している場合は、リポジトリのミラーリングセクションでエラーが表示されます。
APIによるプッシュミラーの設定
リモートミラーAPIを使ってプロジェクトのプッシュミラーを作成したり変更したりすることもできます。
保護されたブランチのみをプッシュ
- GitLab Starter10.3 で導入されました。
- 10.8でGitLabCoreに移行しました。
保護したブランチだけを GitLab からリモートリポジトリにプッシュすることもできます。
このオプションを使用するには、リポジトリのミラーを作成するときに、保護されたブランチだけをミラーするチェックボックスをオンにします。
乖離した審判を維持
GitLab 13.0から導入されました。
デフォルトでは、リモートミラーの ref がローカルリポジトリから乖離している場合、プッシュ全体が失敗し、何も更新されません。
たとえば、master
、develop
、stable
のブランチがあるリポジトリがリモートにミラーされた後、ミラー上のdevelop
に新しいコミットが追加された場合、次のプッシュは失敗し、master
とstable
は分岐していないにもかかわらず、古いままになってしまいます。分岐が解決されるまで、どのブランチの変更もミラーできません。
Keep divergent refsオプションを有効にすると、develop
ブランチがスキップされ、master
とstable
を更新できるようになります。ミラーのステータスには、develop
が分岐してスキップされたことが反映され、更新失敗とマークされます。
GitLabからGitHubへのプッシュミラーの設定
GitLabからGitHubにミラーを設定するには、以下の手順に従う必要があります:
-
public_repo
にチェックを入れてGitHub パーソナルアクセストークンを作成します。 - gitリポジトリの URLフィールドには、次のフォーマットで入力してください:
https://<your_github_username>@github.com/<your_github_group>/<your_github_project>.git
. - パスワード欄にGitHubのパーソナルアクセストークンを入力します。
- リポジトリのミラーボタンをクリックします。
ミラーされたリポジトリが一覧表示されます。例えば、https://*****:*****@github.com/<your_github_group>/<your_github_project>.git
.
リポジトリはすぐにプッシュされます。 強制的にプッシュするには、適切なボタンをクリックしてください。
2FAを有効にしたGitLabインスタンスへのプッシュミラーの設定
- 移動先のGitLabインスタンスで、
write_repository
スコープを持つ個人アクセストークンを作成します。 - ソースのGitLabインスタンスで:
- gitリポジトリの URLフィールドには、次のフォーマットで入力してください:
https://oauth2@<destination host>/<your_gitlab_group_or_name>/<your_gitlab_project>.git
. - Passwordフィールドに、移動先のGitLabインスタンスで作成したGitLabパーソナルアクセストークンを入力します。
- リポジトリのミラーボタンをクリックします。
- gitリポジトリの URLフィールドには、次のフォーマットで入力してください:
リモートリポジトリからのプル
- GitLab Enterprise Edition 8.2で導入されました。
- GitLab Starter11.11でGit LFSをサポートしました。
リポジトリのブランチ、タグ、コミットを上流のリポジトリから自動的に更新するように設定できます。
興味のあるリポジトリが別のサーバーにあり、使い慣れた GitLab のインターフェイスを使ってそのコンテンツやアクティビティを閲覧したい場合に便利です。
既存のプロジェクトにミラープルーを設定するには
- プロジェクトの[Settings(設定)]>[Repository(リポジトリ)]に移動し、[Mirroring repositories(リポジトリのミラーリング)]セクションを展開します。
- リポジトリのURLを入力します。
- ミラーの方向ドロップダウンからプルを選択します。
- 必要に応じて、認証方法ドロップダウンから認証方法を選択します。
- 必要であれば、以下のボックスにチェックを入れてください:
- 分岐したブランチを上書きします。
- ミラーアップデートのパイプラインをトリガーします。
- ミラーで保護されたブランチのみ。
- Mirrorrepository ボタンをクリックして、設定を保存します。
GitLab はアップストリームリポジトリから変更をプルするように設定されているので、コミットを GitLab 上のリポジトリに直接プッシュすべきではありません。 代わりに、コミットはすべてアップストリームリポジトリにプッシュする必要があります。 アップストリームリポジトリにプッシュされた変更は、GitLab リポジトリにもプルされます:
- 一定期間内に自動的に
- 強制アップデートが開始された場合。
どのように動作するか
リポジトリに対してプルミラーリング機能が有効になると、リポジトリはキューに追加されます。
1分間に1回、Sidekiq cronジョブがリポジトリミラーの更新をスケジュールします:
- 利用可能な容量。 これはSidekiqの設定によって決まります。 GitLab.comについては、GitLab.com Sidekiqの設定を参照してください。
- キューにあるリポジトリミラーのうち、更新期限が来ているものの数です。 期限が来ているかどうかは、リポジトリミラーが最後に更新されたタイミングと、何回再試行されたかに依存します。
リポジトリミラーは、Sidekiqがそれらを処理できるようになると更新されます。 リポジトリミラーの更新処理が行われた場合:
- 成功した場合、更新は少なくとも30分待ちで再度キューに入れられます。
- 失敗した場合 (たとえばブランチがアップストリームから逸脱した場合など)、後で再試行されます。 ミラーは最大 14 回まで失敗する可能性があり、それ以降は更新キューに入れられなくなります。
SSH認証
- GitLab Starter9.5でPullミラーリングに導入されました。
- GitLabCore11.6でPushミラーリングが導入されました。
SSH認証は相互認証です:
- リポジトリへのアクセスが許可されていることをサーバーに証明する必要があります。
- サーバーはまた、そのサーバーが実在することを証明しなければなりません。
あなたは自分の認証情報をパスワードまたは公開鍵として提供し、もう一方のリポジトリが存在するサーバーはその認証情報を「ホスト鍵」として提供し、そのフィンガープリントを手動で検証する必要があります。
SSH 経由でミラーリングしている (ssh://
URL を使っている) 場合は、次のようにして認証します:
- HTTPS と同様、パスワードベースの認証。
- 公開鍵認証:これはパスワード認証よりもセキュリティが高いことが多く、特に相手リポジトリがデプロイ鍵をサポートしている場合に有効です。
始めるには
- プロジェクトの[Settings(設定)]>[Repository(リポジトリ)]に移動し、[Mirroring repositories(リポジトリのミラーリング)]セクションを展開します。
- ミラーリング用の
ssh://
URL を入力します。
git@example.com:group/project.git
)は、現時点ではサポートされていません。URLを入力すると、ページに2つのボタンが追加されます:
- ホストキーの検出。
- ホストキーを手動で入力します。
をクリックします:
- Detect host keysボタンを押すと、GitLabはサーバーからホストキーを取得し、フィンガープリントを表示します。
- ホストキーを手動で入力ボタンを押すと、ホストキーを貼り付けるフィールドが表示されます。
GitLab.com や他のコードホスティングサイトはフィンガープリントを公開し、チェックできるようにしています:
セルフマネジメントの GitLab を使っている場合や、他のリポジトリのサーバーにアクセスできる場合は、安全にフィンガープリントを集めることができます:
$ cat /etc/ssh/ssh_host*pub | ssh-keygen -E md5 -l -f -
256 MD5:f4:28:9f:23:99:15:21:1b:bf:ed:1f:8e:a0:76:b2:9d root@example.com (ECDSA)
256 MD5:e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73 root@example.com (ED25519)
2048 MD5:3f:72:be:3d:62:03:5c:62:83:e8:6e:14:34:3a:85:1d root@example.com (RSA)
-E md5
を除外する必要があるかもしれません。リポジトリをミラーリングするとき、GitLab は接続する前に、保存されているホストキーの少なくとも一つが一致することをチェックするようになりました。 これにより、悪意のあるコードがミラーに注入されたり、パスワードが盗まれたりするのを防ぐことができます。
SSH公開キー認証
SSH 公開鍵認証を使うには、Authentication methodドロップダウンからそのオプションを選択する必要があります。 ミラーが作成されると、GitLab は 4096 ビットの RSA 鍵を生成します。この鍵はCopy SSH public keyボタンをクリックしてコピーできます。
その後、公開SSHキーを他のリポジトリの設定に追加する必要があります:
- もう一方のリポジトリが GitLab でホストされている場合は、公開 SSH キーをデプロイキーとして追加します。
- 他のリポジトリが別の場所でホストされている場合は、ユーザーの
authorized_keys
ファイルにキーを追加する必要があるかもしれません。 公開 SSH キーをすべてファイルに行単位で貼り付けて保存してください。
いつでもキーを変更する必要がある場合は、ミラーを削除して再追加することで新しいキーを生成できます。 ミラーを実行し続けるには、新しいキーでもう一方のリポジトリを更新する必要があります。
分岐ブランチの上書き
GitLab Starter10.6 で導入されました。
ローカルブランチとリモートのバージョンが異なっていても、常にリモートのバージョンで更新するように設定できます。
このオプションを使用するには、リポジトリミラーを作成するときに分岐ブランチを上書きするチェックボックスをオンにします。
ミラーで保護されたブランチのみ
GitLab Starter10.3 で導入されました。
リモートリポジトリから GitLab に保護ブランチのみをプルミラーすることができます。 保護されていないブランチはミラーされず、分岐する可能性があります。
このオプションを使用するには、リポジトリのミラーを作成するときに、保護されたブランチだけをミラーするチェックボックスをオンにします。
ハード障害
GitLab Starter10.2 で導入されました。
ミラーリング処理が14回連続で失敗すると、ハード的に失敗したとマークされます。 このマークは、以下のいずれかに表示されます:
- プロジェクトのメインダッシュボード。
- プルミラーの設定ページ。
プロジェクトがハードフェイルされると、そのプロジェクトはミラーリングのためにピックアップされなくなります。 ユーザーは、強制更新によってプロジェクトのミラーリングを再開することができます。
APIを使用した更新のトリガー
GitLab Starter10.3 で導入されました。
プルミラーリングは、ポーリングを使って上流に追加された新しいブランチやコミットを検知します。APIでGitLabに通知すると、更新は即座にプルされます。
詳細については、プロジェクトのプルミラーリングプロセスの開始を参照してください。
強制更新
ミラーは自動的に更新されるようにスケジュールされていますが、リポジトリ設定ページのミラーリングリポジトリセクションにある更新ボタンを使用することで、いつでも強制的に更新することができます。
双方向ミラーリング
GitLab リポジトリを同じリモートソースからプルしたりプッシュしたりするように設定した場合、どちらのリポジトリも正しく更新される保証はありません。 リポジトリを双方向ミラーリングするように設定した場合は、起こりうるコンフリクトに備えて、誰がどのように解決するかを決めておく必要があります。
ミラーリングされたコミットをどちらかのリモートで書き換えると、コンフリクトが発生し、ミラーリングが失敗します。 これは以下の方法で防ぐことができます:
履歴の書き換えによる競合を防ぐため、両方のリモートでミラーしたいブランチを保護する必要があります。
双方向ミラーリングは、同じブランチに近いタイミングでコミットすると競合が発生するという競合状態も引き起こします。 この競合状態は、Push イベントwebhook を使って GitLab への即時プルをトリガーすることで、ミラーリングの遅延を減らすことで緩和できます。 GitLab からのプッシュミラーリングは、保護されたブランチをプッシュミラーリングする場合のみ、1 分間に 1 回にレートが制限されます。
GitLab への即時プルをトリガーする webhook の設定
アップストリームの GitLab インスタンスでプッシュと プルのミラーを設定済みだとすると、上記のように即座にプルをトリガーするには、ダウンストリームのインスタンスでPush Event Web Hookを設定する必要があります。
そのためには:
-
API
のスコープで個人アクセストークンを作成します。 - 設定 >Webhooksに移動します。
-
Webhook URL を追加します。この場合、リポジトリが更新されたら即座にプルするためにPull Mirror APIリクエストを使用します。
https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token>
- プッシュイベント]チェックボックスが選択されていることを確認します。
- Add Webhookボタンをクリックして webhook を保存します。
- インテグレーションをテストするにはTestボタンをクリックし、GitLabがエラーを返さないことを確認します。
pre-receive
フックを使用したコンフリクトの防止
サーバーサイドのpre-receive
フックを使うことで、上流の Git リポジトリにコミットをプッシュした後でプッシュを受け付けるようにすることができます。 この設定では、一方の Git リポジトリが上流、もう一方が下流となります。pre-receive
フックは下流のリポジトリにインストールされます。
GitLabサーバーのServer hooksの設定についてはこちらをご覧ください。
pre-receive
フックのサンプルを以下に示します。
#!/usr/bin/env bash
# --- Assume only one push mirror target
# Push mirroring remotes are named `remote_mirror_<id>`, this finds the first remote and uses that.
TARGET_REPO=$(git remote | grep -m 1 remote_mirror)
proxy_push()
{
# --- Arguments
OLDREV=$(git rev-parse $1)
NEWREV=$(git rev-parse $2)
REFNAME="$3"
# --- Pattern of branches to proxy pushes
allowlist=$(expr "$branch" : "\(master\)")
case "$refname" in
refs/heads/*)
branch=$(expr "$refname" : "refs/heads/\(.*\)")
if [ "$allowlist" = "$branch" ]; then
unset GIT_QUARANTINE_PATH # handle https://git-scm.com/docs/git-receive-pack#_quarantine_environment
error="$(git push --quiet $TARGET_REPO $NEWREV:$REFNAME 2>&1)"
fail=$?
if [ "$fail" != "0" ]; then
echo >&2 ""
echo >&2 " Error: updates were rejected by upstream server"
echo >&2 " This is usually caused by another repository pushing changes"
echo >&2 " to the same ref. You may want to first integrate remote changes"
echo >&2 ""
return
fi
fi
;;
esac
}
# Allow dual mode: run from the command line just like the update hook, or
# if no arguments are given then run as a hook script
if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
# Output to the terminal in command line mode - if someone wanted to
# resend an email; they could redirect the output to sendmail
# themselves
PAGER= proxy_push $2 $3 $1
else
# Push is proxied upstream one ref at a time. Because of this it is possible
# for some refs to succeed, and others to fail. This will result in a failed
# push.
while read oldrev newrev refname
do
proxy_push $oldrev $newrev $refname
done
fi
なお、このサンプルにはいくつかの制限があります:
- この例は、あなたのユースケースにそのまま当てはまらないかもしれませんし、修正が必要かもしれません。
- ミラーのさまざまな種類の認証メカニズムについては考慮されていません。
- 強制アップデート(履歴の書き換え)では動作しません。
-
allowlist
パターンにマッチするブランチのみがプロキシプッシュされます。
- このスクリプトはGitフックの検疫環境を回避します。なぜなら、
$TARGET_REPO
のアップデートはrefアップデートとみなされ、Gitはそれについて文句を言うからです。
Git Fusion による Perforce Helix のミラーリング
Git Fusionは Perforce HelixのGitインターフェースを提供し、GitLabでプロジェクトを双方向にミラーリングすることができます。 これは、Perforce HelixからGitLabに移行する際に、重複しているPerforce Helixワークスペースを同時にGitLabに移行できない場合に便利です。
Perforce Helix でミラーリングを使用する場合は、保護されたブランチのみをミラーリングしてください。 Perforce Helix は、履歴を書き換えるようなプッシュを拒否します。 Git Fusion のパフォーマンス制限のため、ミラーリングするブランチは最少数だけにしてください。
Git Fusion 経由で Perforce Helix のミラーリングを設定する場合は、以下の Git Fusion 設定を推奨します:
-
change-pusher
そうしないと、すべてのコミットが、既存の Perforce Helix ユーザやunknown_git
ユーザにマッピングされるのではなく、ミラーリングアカウントによってコミットされたものとして書き換えられてしまいます。 -
unknown_git
ユーザーは、Perforce Helix に GitLab ユーザーが存在しない場合にコミット作成者として使用されます。
GitFusion の設定については、Perforce.comをご覧ください。
トラブルシューティング
プッシュ中にエラーが発生した場合、GitLab はそのリポジトリに “エラー” のハイライトを表示します。 エラーの詳細は、ハイライトテキストにカーソルを合わせることで確認できます。
13:GitHubでエラーコード2のRST_STREAMを受信しました。
GitHub リポジトリにミラーリングしているときに “13:Received RST_STREAM with error code 2” というメッセージが表示される場合は、GitHub の設定で、コミットで使用した自分のメールアドレスを公開するプッシュをブロックするように設定されている可能性があります。 GitHub で自分のメールアドレスを公開するように設定するか、Block command line pushes that expose my emailの設定を無効にしてください。