仓库镜像 (BASIC ALL)

您可以镜像外部源的仓库。您可以选择作为源的仓库。可以自动同步分支、标签和提交。

note支持 SCP 样式的 URL。

存在几种镜像方法:

  • 推送:将极狐GitLab 中的仓库镜像到另一个位置。
  • 拉取:将仓库从另一个位置镜像到极狐GitLab 专业版实例。
  • 双向镜像也可用,但会导致冲突。

在以下情况镜像仓库:

  • 您的项目的规范版本已迁移到极狐GitLab。要在以前的家中继续提供项目的副本,请将您的极狐GitLab 仓库配置为推送镜像。您对极狐GitLab 仓库所做的更改将复制到旧位置。
  • 您的实例是私有的,但您想开源一些项目。
  • 您迁移到极狐GitLab,但您的项目的规范版本在其他地方。将您的极狐GitLab 仓库配置为另一个项目的拉取镜像。您的极狐GitLab 仓库会提取项目的提交、标签和分支的副本。它们可以在极狐GitLab 上使用。

创建仓库镜像

先决条件:

  • 您必须至少具有项目的维护者角色。
  • 如果您的镜像使用 ssh:// 连接,则主机密钥必须可在服务器上检测到,或者您必须拥有该密钥的本地副本。
  1. 在左侧边栏中,选择 搜索或转到 并找到您的项目。
  2. 在左侧边栏中,选择 设置 > 仓库
  3. 展开 镜像仓库
  4. 输入 Git 仓库 URL。出于安全原因,原始仓库的 URL 仅向镜像项目中具有维护者角色或所有者角色的用户展示。
  5. 选择 镜像方向
  6. 如果您输入了 ssh:// URL,请选择:
    • 检测主机密钥:极狐GitLab 从服务器获取主机密钥并显示指纹。
    • 手动输入主机密钥,并将主机密钥输入 SSH 主机密钥

    在镜像仓库时,极狐GitLab 在连接之前确认至少一个存储的主机密钥匹配。此检查可以保护您的镜像免受恶意代码注入或您的密码被盗。

  7. 选择 验证方式
  8. 如果您使用 SSH 主机密钥进行身份验证,请验证主机密钥以确保其正确无误。
  9. 为防止强制推送不同的 refs,请选择 保留分叉的 refs
  10. 可选。选择 仅镜像受保护的分支
  11. 选择 镜像仓库

如果您选择 SSH 公钥 作为您的身份验证方法,极狐GitLab 会为您的 GitLab 仓库生成一个公钥。您必须将此密钥提供给非 GitLab 服务器。 要了解更多信息,请阅读获取您的 SSH 公钥

更新镜像

更新镜像仓库后,所有新分支、标签和提交都将在项目的活动源中可见。极狐GitLab 的仓库镜像会自动更新。 您还可以手动触发更新:

  • 根据管理员在私有化部署实例上设置的拉取镜像间隔限制。

强制更新

虽然镜像计划自动更新,但您可以强制立即更新,除非:

  • 镜像已经在更新。
  • 拉取镜像限制的间隔(以秒为单位)在上次更新后尚未结束。

先决条件:

  • 您必须至少具有项目的维护者角色。
  1. 在左侧边栏中,选择 搜索或转到 并找到您的项目。
  2. 在左侧边栏中,选择 设置 > 仓库
  3. 展开 镜像仓库
  4. 滚动到 镜像的仓库 并确定要更新的镜像。
  5. 选择 立即更新): Repository mirroring force update user interface

仅镜像受保护的分支

您可以选择仅从或向远端镜像镜像项目中的受保护分支。 对于拉取镜像,镜像项目中的非保护分支不进行镜像,可以发散。

您可以选择仅将镜像项目中的受保护分支,镜像到远端仓库或从远端仓库镜像。对于拉取镜像,镜像项目中的非保护分支不进行镜像,可以分叉。

要使用此选项,请在创建仓库镜像时选择 仅镜像受保护的分支

镜像特定分支

  • 镜像名称匹配正则表达式的分支引入于极狐GitLab 15.8,功能标志mirror_only_branches_match_regex。默认禁用。
  • 默认启用于 16.0 版本。
在私有化部署的极狐GitLab 上,默认情况下字段 mirror_branch_regex 可用。 要隐藏此功能,请让管理员禁用名为 mirror_only_branches_match_regex功能标志。 在 JihuLab.com 上,此功能可用。

仅镜像名称与 re2 正则表达式匹配的分支, 在 镜像特定分支 字段中输入正则表达式。名称与正则表达式不匹配的分支不会被镜像。

镜像的验证方法

创建镜像时,必须为其配置身份验证方法。 极狐GitLab 支持以下身份验证方法:

使用密码身份验证时,请确保指定用户名。 对于项目访问令牌群组访问令牌,使用用户名(不是令牌名称)和令牌作为密码。

SSH 验证

SSH 身份验证是相互的:

  • 您必须向服务器证明您有权访问仓库。
  • 服务器还必须向您证明它声明的是谁。

对于 SSH 身份验证,您提供您的凭据作为密码或公钥。 其它仓库所在的服务器提供其凭据作为主机密钥。 您必须手动验证此主机密钥的指纹

如果您通过 SSH 进行镜像(使用 ssh:// URL),您可以使用以下方法进行身份验证:

  • 基于密码的身份验证,就像通过 HTTPS 一样。
  • 公钥验证。这种方法通常比密码验证更安全,尤其是当其它仓库支持部署密钥时。

获取您的 SSH 公钥

当您镜像仓库并选择 SSH 公钥 作为您的身份验证方法时,极狐GitLab 会为您生成一个公钥。非 GitLab 服务器需要此密钥才能与您的 GitLab 仓库建立信任。要复制您的 SSH 公钥:

  1. 在左侧边栏中,选择 搜索或转到 并找到您的项目。
  2. 在左侧边栏中,选择 设置 > 仓库
  3. 展开 镜像仓库
  4. 滚动到 镜像的仓库
  5. 确定正确的仓库,然后选择 复制 SSH 公钥 ()。
  6. 将公共 SSH 密钥添加到另一个仓库的配置中:
    • 如果另一个仓库托管在极狐GitLab 上,请将公共 SSH 密钥添加为部署密钥。
    • 如果其它仓库托管在别处,请将密钥添加到您用户的 authorized_keys 文件中。将整个公共 SSH 密钥粘贴到文件中单独一行并保存。

如果您必须随时更改密钥,可以删除并重新添加镜像以生成新密钥。使用新密钥更新另一个仓库以保持镜像运行。

note生成的密钥存储在 GitLab 数据库中,而不是文件系统中。因此,不能在预接收 hook 中使用镜像的 SSH 公钥认证。

验证主机密钥

使用主机密钥时,请始终验证指纹是否符合您的预期。

如果您符合以下条件,则可以使用以下命令安全地收集密钥指纹:

  • 运行私有化部署版极狐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)

旧版本的 SSH 可能需要您从命令中删除 -E md5

故障排查

如果在推送过程中发生错误,极狐GitLab 会为该仓库显示 错误 突出显示。然后可以通过将鼠标悬停在突出显示文本上来查看错误的详细信息。

Received RST_STREAM with error code 2 with GitHub

如果您在镜像到 GitHub 仓库时收到此消息:

13:Received RST_STREAM with error code 2

您的 GitHub 设置可能设置为阻止公开您在提交中使用的电子邮件地址的推送。要解决此问题,请执行以下任一操作:

超过最后期限

升级到更高版本时,用户名表示方式的更改意味着您必须更新镜像用户名和密码,以确保将 %40 字符替换为 @

Connection blocked because server only allows public key authentication

极狐GitLab 和远程存储库之间的连接被阻止。即使 TCP 检查成功,您必须检查从 GitLab 到远程服务器的路由中的任何网络组件是否被阻塞。

当防火墙对传出数据包执行“深度 SSH 检查”时,可能会发生此错误。

Could not read username: terminal prompts disabled

如果在使用 GitLab CI/CD for external repositories 创建新项目后收到此错误:

  • Bitbucket Cloud:

    "2:fetch remote: "fatal: could not read Username for 'https://bitbucket.org':
    terminal prompts disabled\n": exit status 128."
    
  • Bitbucket Server(私有化部署):

    "2:fetch remote: "fatal: could not read Username for 'https://lab.example.com':
    terminal prompts disabled\n": exit status 128.
    

检查镜像仓库的 URL 中是否指定了仓库所有者:

  1. 在左侧边栏中,选择 搜索或转到 并找到您的项目。
  2. 在左侧边栏中,选择 设置 > 仓库
  3. 展开 镜像仓库
  4. 如果没有指定仓库所有者,请删除并以这种格式再次添加 URL,将 OWNERACCOUNTNAMEPATH_TO_REPOREPONAME 替换为您的值:

    • Bitbucket Cloud:

      https://OWNER@bitbucket.org/ACCOUNTNAME/REPONAME.git
      
    • Bitbucket Server(私有化部署):

      https://OWNER@lab.example.com/PATH_TO_REPO/REPONAME.git
      

连接到 Bitbucket Cloud 或 Bitbucket Server 仓库进行镜像时,字符串中需要仓库所有者。

拉取镜像缺少 LFS 文件

在某些情况下,拉取镜像不会传输 LFS 文件。在以下情况下会出现此问题:

  • 您使用 SSH 存储库 URL。解决方法是改用 HTTPS 存储库 URL。
  • 您使用的是 14.0 或更早版本,并且源存储库是公共 Bitbucket URL。在 14.0.6 版本中修复。
  • 您使用对象存储来镜像外部仓库。

无效 URL

如果您在通过 SSH 设置镜像时收到此错误,请确保 URL 的格式有效。

镜像不支持 SSH 克隆 URL 的短版本(git@jihulab.com:gitlab-cn/gitlab.git),需要包含协议的完整版本(ssh://git@jihulab.com/gitlab-cn/gitlab.git)。

确保使用 / 而不是 : 分隔主机和项目路径。

主机密钥验证失败

当目标主机公开 SSH 密钥更改时会返回此错误。SSH 公钥很少更改,如果主机密钥验证失败,但您怀疑密钥仍然有效,您可以刷新密钥信息。

先决条件:

  • 您必须至少具有项目的维护者角色。

要解决此问题:

  1. 验证主机密钥
  2. 在左侧边栏中,选择 搜索或转到 并找到您的项目。
  3. 在左侧边栏中,选择 设置 > 仓库
  4. 展开 镜像仓库
  5. 要刷新密钥,可以:

    • 选择 检测主机密钥 以便极狐GitLab 从服务器获取主机密钥,并显示指纹。
    • 选择 手动输入主机密钥,然后将主机密钥输入到 SSH 主机密钥 字段中。
  • 选择 镜像仓库

在 Rails 控制台中将镜像用户和令牌转移到单个服务账户

这需要访问 Rails 控制台

用例:如果您有多个用户使用他们自己的 GitHub 凭据来设置代码库镜像,当人们离开公司时镜像会中断。使用此脚本将不同的镜像用户和令牌迁移到单个服务账户中:

caution无论运行是否正确,更改数据的命令可能会造成损坏。始终首先在测试环境中运行命令,并准备好备份实例以进行恢复。
svc_user = User.find_by(username: 'ourServiceUser')
token = 'githubAccessToken'

Project.where(mirror: true).each do |project|
  import_url = project.import_url

  # The url we want is https://token@project/path.git
  repo_url = if import_url.include?('@')
               # Case 1: The url is something like https://23423432@project/path.git
               import_url.split('@').last
             elsif import_url.include?('//')
               # Case 2: The url is something like https://project/path.git
               import_url.split('//').last
             end

  next unless repo_url

  final_url = "https://#{token}@#{repo_url}"

  project.mirror_user = svc_user
  project.import_url = final_url
  project.username_only_import_url = final_url
  project.save
end