双向镜像

移动到专业版 13.9 版本。

caution双向镜像可能会导致冲突。

双向镜像将两个仓库配置为相互拉取和推送。无法保证任一仓库都可以无错误地更新。

减少双向镜像中的冲突

如果您配置双向镜像,请准备您的仓库以应对冲突。进行以下配置以减少冲突,以及如何在它们发生时解决它们:

  • 仅镜像受保护的分支。重写任一远端上的任何镜像提交都会导致冲突和镜像失败。
  • 保护您想在两个远端上进行镜像的分支,以防止重写历史引起冲突。
  • 使用推送事件 webhook 减少镜像延迟。双向镜像会产生竞争条件,靠近同一分支的提交会导致冲突。推送事件 webhook 可以帮助缓解竞争条件。当仅推送镜像受保护的分支时,来自极狐GitLab 的推送镜像的速率限制为每分钟一次。
  • 使用 pre-receive hook防止冲突。

配置 webhook 以触发立即拉到极狐GitLab

下游实例中的推送事件 webhook 可以通过更频繁地同步更改来帮助减少竞争条件。

先决条件:

  • 您已经在上游实例中的镜像配置了推送拉取

在下游实例中创建 webhook:

  1. 创建一个个人访问令牌API 范围。
  2. 在顶部栏上,选择 主菜单 > 项目 并找到您的项目。
  3. 在左侧边栏上,选择 设置 > Webhooks
  4. 添加 webhook URL,它(在本例中)使用拉取镜像 API 请求在仓库更新后触发立即拉取:

    https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token>
    
  5. 选择 推送事件
  6. 选择 添加 Webhook

要测试集成,请选择 测试 并确认极狐GitLab 不返回错误消息。

使用 pre-receive hook 防止冲突

caution此解决方案会对 Git 推送操作的性能产生负面影响,因为它们被代理到上游 Git 仓库。

在此配置中,一个 Git 仓库充当权威上游,另一个充当下游。这个服务器端的 pre-receive hook 只有在第一次将提交推送到上游仓库之后才接受推送。在您的下游存储库上安装此 hook。

例如:

#!/usr/bin/env bash

# --- Assume only one push mirror target
# Push mirroring remotes are named `remote_mirror_<id>`.
# This line 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
        # handle 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 " 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. It is possible for some refs
  # to succeed, and others to fail. This results in a failed push.
  while read oldrev newrev refname
  do
    proxy_push $oldrev $newrev $refname
  done
fi

此示例有一些限制:

  • 如果不修改,它可能不适用于您的用例:
    • 它不考虑镜像的不同类型的身份验证机制。
    • 它不适用于强制更新(重写历史记录)。
    • 只有与 allowlist 模式匹配的分支才会被代理推送。
  • 该脚本绕过了 Git hook 隔离环境,因为 $TARGET_REPO 的更新被视为 ref 更新,并且 Git 会显示有关它的警告。

使用 Perforce Helix 与 Git Fusion 镜像

移动到专业版于 13.9 版本。

caution双向镜像不应用作永久配置。

Git Fusion 提供了一个 Git 接口到 Perforce Helix。极狐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 用户。
  • 如果 Perforce Helix 中不存在 GitLab 用户,则使用 unknown_git 用户作为提交作者。

阅读 Perforce.com 上的 Git Fusion 设置