双向镜像
- Tier: Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
双向镜像可能会导致冲突。
双向 镜像 配置两个仓库互相拉取和推送。无法保证任何一个仓库都能无错误地更新。
减少双向镜像中的冲突
如果您配置了双向镜像,请为您的仓库做好冲突准备。配置它们以减少冲突,并在冲突发生时解决冲突:
- 仅镜像受保护的分支。在任何远程仓库上重写任何镜像的提交都会导致冲突和镜像失败。
- 在两个远程仓库上保护您想要镜像的分支,以防止因重写历史而导致的冲突。
- 使用推送事件 webhook减少镜像延迟。双向镜像会产生竞态条件,即对同一分支的提交时间相近会导致冲突。推送事件 webhook 可以帮助缓解竞态条件。当仅推送镜像受保护的分支时,GitLab 的推送镜像受到每分钟一次的速率限制。
- 使用 pre-receive hook防止冲突。
配置 webhook 以触发立即拉取到 GitLab
下游实例中的推送事件 webhook可以通过更频繁地同步变更来帮助减少竞态条件。
先决条件:
要在下游实例中创建 webhook:
-
创建具有
API范围的个人访问令牌。 -
在左侧边栏,选择搜索或转到并找到您的项目。
-
选择设置 > Webhooks。
-
添加 webhook URL,在此情况下,它使用拉取镜像 API请求在仓库更新后触发立即拉取:
https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token> -
选择推送事件。
-
选择添加 Webhook。
要测试集成,选择测试并确认 GitLab 没有返回错误消息。
使用 pre-receive hook 防止冲突
此解决方案会负面影响 Git push 操作的性能,因为它们被代理到上游 Git 仓库。
在此配置中,一个 Git 仓库作为权威的上游,另一个作为下游。此服务器端的 pre-receive hook 仅在首先将提交推送到上游仓库后才接受推送。请将此 hook 安装在您的下游仓库上。
例如:
#!/usr/bin/env bash
# --- 假设只有一个推送镜像目标
# 推送镜像远程仓库命名为 `remote_mirror_<id>`。
# 这行找到第一个远程仓库并使用它。
TARGET_REPO=$(git remote | grep -m 1 remote_mirror)
proxy_push()
{
# --- 参数
OLDREV=$(git rev-parse $1)
NEWREV=$(git rev-parse $2)
REFNAME="$3"
# --- 要代理推送的分支模式
allowlist=$(expr "$branch" : "\(master\)")
case "$refname" in
refs/heads/*)
branch=$(expr "$refname" : "refs/heads/\(.*\)")
if [ "$allowlist" = "$branch" ]; then
# 处理 https://git-scm.com/docs/git-receive-pack#_quarantine_environment
unset GIT_QUARANTINE_PATH
error="$(git push --quiet $TARGET_REPO $NEWREV:$REFNAME 2>&1)"
fail=$?
if [ "$fail" != "0" ]; then
echo >&2 ""
echo >&2 " 错误:更新被上游服务器拒绝"
echo >&2 " 这通常是由另一个仓库推送变更到同一引用引起的。您可能需要先集成远程变更"
echo >&2 ""
return
fi
fi
;;
esac
}
# 允许双重模式:像 update hook 一样从命令行运行,或者
# 如果没有给出参数,则作为 hook 脚本运行:
if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
# 在命令行模式下输出到终端。如果有人想要
# 重新发送电子邮件,他们可以自己将输出重定向到 sendmail
PAGER= proxy_push $2 $3 $1
else
# Push 被代理到上游,一次一个 ref。有些 refs
# 可能成功,而其他可能失败。这会导致推送失败。
while read oldrev newrev refname
do
proxy_push $oldrev $newrev $refname
done
fi此示例有一些局限性:
- 如果不修改,它可能不适用于您的用例:
- 它不考虑镜像的不同类型的认证机制。
- 它不适用于强制更新(重写历史)。
- 只有匹配
allowlist模式的分支才会被代理推送。
- 该脚本绕过了 Git hook 隔离环境,因为
$TARGET_REPO的更新被视为 ref 更新,Git 会显示相关警告。
使用 Perforce Helix 和 Git Fusion 进行镜像
- Tier: Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
双向镜像不应作为永久配置使用。请参考从 Perforce Helix 迁移了解替代的迁移方法。
Git Fusion 为 Perforce Helix 提供 Git 接口。GitLab 可以使用 Perforce Helix 接口双向镜像项目。当重叠的 Perforce Helix 工作空间无法同时迁移时,它可以帮助从 Perforce Helix 迁移到 GitLab。
如果您使用 Perforce Helix 进行镜像,请仅镜像受保护的分支。Perforce Helix 会拒绝任何重写历史的推送。由于 Git Fusion 的性能限制,应该镜像最少数量的分支。
当您使用 Git Fusion 配置与 Perforce Helix 的镜像时,您应该使用这些 Git Fusion 设置:
- 禁用
change-pusher。否则,每个提交都会被重写为由镜像账户提交,而不是映射到现有的 Perforce Helix 用户或unknown_git用户。 - 如果 GitLab 用户在 Perforce Helix 中不存在,请使用
unknown_git用户作为提交作者。