Help us learn about your current experience with the documentation. Take the survey.

将您的项目从 GitHub 导入到 GitLab

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

您可以从 GitHub.com 或 GitHub Enterprise 导入您的 GitHub 项目。导入项目不会 将 GitHub 中的任何类型的群组或组织迁移或导入到 GitLab。

导入的问题、合并请求、评论和事件在 GitLab 中都有 Imported 标识。

命名空间是 GitLab 中的用户或群组,例如 gitlab.com/sidney-jonesgitlab.com/customer-success

使用 GitLab UI,GitHub 导入器总是从 github.com 域导入。如果您要从自托管 GitHub Enterprise Server 域导入,请使用 GitLab Import API GitHub 端点,并搭配具有 api 权限的 GitLab 访问令牌。

您可以在导入之前更改目标命名空间和目标仓库名称。

有关导入过程的概述,请参阅 如何从 GitHub 迁移到 GitLab(包括 Actions)

估算导入时长

每次从 GitHub 导入都不同,这会影响您执行的导入时长。然而,在我们的测试中, 我们在 76 小时内导入了 https://github.com/kubernetes/kubernetes。测试时,该项目包含:

  • 80,000 个拉取请求。
  • 45,000 个问题。
  • 约 150 万条评论。

先决条件

要从 GitHub 导入项目,您必须启用 GitHub 导入源。 如果未启用该导入源,请要求您的 GitLab 管理员启用它。GitHub 导入源在 GitLab.com 上默认启用。

权限和角色

要使用 GitHub 导入器,您必须拥有:

  • 对要导入的 GitHub 项目的访问权限。
  • 在目标 GitLab 群组中至少拥有 Maintainer 角色。

此外,GitHub 仓库所属的组织不得对您导入到的 GitLab 实例施加 第三方应用程序访问策略 的限制。

用户贡献映射的账户

在使用 旧的用户贡献映射方法 导入到 GitLab Self-Managed 和 GitLab Dedicated 之前,您必须满足某些要求。导入到 GitLab.com 使用 改进的方法, 无需准备。

这些要求是:

  • 仓库中的每个 GitHub 作者和被指派人必须拥有 公开的电子邮件地址
  • GitHub 用户的电子邮件地址必须与其 GitLab 电子邮件地址匹配。
  • 如果 GitHub 中的用户电子邮件地址在 GitLab 中设置为次要电子邮件地址,他们必须确认它。

GitHub Enterprise 不需要公开的电子邮件地址,因此您可能需要将其添加到现有账户中。

已知问题

  • 2017 年之前创建的 GitHub 拉取请求评论(在 GitLab 中称为差异注释)会在单独的线程中导入。 这是因为 GitHub API 的限制,2017 年之前的评论不包含 in_reply_to_id

  • 由于 已知问题,来自 GitHub Enterprise Server 实例上仓库的 Markdown 附件不会被导入。

  • 由于 已知问题,在导入使用 GitHub 自动合并 的项目时,如果提交使用 GitHub 内部 GPG 密钥签名,导入到 GitLab 中的项目可能有标记为 unverified 的合并提交。

  • GitLab 无法导入 2023-05-09 之前上传到私有仓库的 GitHub Markdown 图片附件。如果您遇到此问题,希望帮助我们解决问题,并愿意为我们提供示例仓库, 请在 issue 424046 中添加评论,我们会联系您。

  • 对于 GitLab 特定引用,GitLab 使用 # 字符表示问题,使用 ! 字符表示合并请求。 但是,GitHub 对问题和拉取请求都只使用 # 字符。导入时:

    • 注释笔记,GitLab 只创建到问题的链接,因为 GitLab 无法确定引用指向的是问题还是合并请求。
    • 问题或合并请求描述,GitLab 不会为任何引用创建链接,因为它们的导入副本可能尚未在目标位置创建。

将您的 GitHub 仓库导入到 GitLab

您可以通过以下方式导入您的 GitHub 仓库:

如果从 github.com 导入,您可以使用任何方法导入。自托管 GitHub Enterprise Server 客户必须使用 API。

使用 GitHub OAuth

如果您要导入到 GitLab.com 或已配置 GitHub OAuth configured 的 GitLab Self-Managed,您可以使用 GitHub OAuth 导入您的仓库。

此方法比使用 个人访问令牌 (PAT) 有优势, 因为后端会交换具有适当权限的访问令牌。

  1. 在左侧边栏顶部,选择 Create new plus )和 New project/repository
  2. 选择 Import project,然后选择 GitHub
  3. 选择 Authorize with GitHub
  4. 继续 选择要导入的仓库

要在执行这些步骤后使用其他方法执行导入,请退出您的 GitLab 账户并重新登录。

使用 GitHub 个人访问令牌

要使用 GitHub 个人访问令牌导入您的 GitHub 仓库:

  1. 生成 GitHub 个人访问令牌。仅支持 classic 个人访问令牌。
    1. 访问 https://github.com/settings/tokens/new
    2. Note 字段中输入令牌描述。
    3. 选择 repo 权限。
    4. 可选。要 导入协作者,或者如果您的项目有 Git LFS 文件,请选择 read:org 权限。
    5. 选择 Generate token
  2. 在 GitLab 左侧边栏顶部,选择 Create new plus )和 New project/repository
  3. 选择 Import project,然后选择 GitHub
  4. 选择 Authorize with GitHub
  5. Personal access token 字段中粘贴 GitHub 个人访问令牌。
  6. 选择 Authenticate
  7. 继续 选择要导入的仓库

要在执行这些步骤后使用不同的令牌执行导入,请退出您的 GitLab 账户并重新登录,或者在 GitHub 中撤销旧的令牌。

使用 API

GitLab REST API 可用于导入 GitHub 仓库。它比使用 GitLab UI 有一些优势:

  • 可以用于导入您不拥有的公共 GitHub 仓库。
  • 可以用于导入自托管的 GitHub Enterprise Server。
  • 可以用于设置 UI 中不可用的 timeout_strategy 选项。

REST API 仅限于使用 GitLab 个人访问令牌进行身份验证。

要使用 GitLab REST API 导入您的 GitHub 仓库:

  1. 生成 GitHub 个人访问令牌。仅支持 classic 个人访问令牌。
    1. 访问 https://github.com/settings/tokens/new
    2. Note 字段中输入令牌描述。
    3. 选择 repo 权限。
    4. 可选。要 导入协作者,或者如果您的项目有 Git LFS 文件,请选择 read:org 权限。
    5. 选择 Generate token
  2. 使用 GitLab REST API 导入您的 GitHub 仓库。

过滤仓库列表

授权访问您的 GitHub 仓库后,GitLab 会将您重定向到导入器页面,并显示您的 GitHub 仓库列表。

使用以下选项卡之一过滤仓库列表:

  • Owner(默认):过滤到您拥有的仓库列表。
  • Collaborated:过滤到您有贡献的仓库列表。
  • Organization:过滤到您所属组织的仓库列表。

选择 Organization 选项卡时,您可以从下拉列表中选择可用的 GitHub 组织来进一步缩小搜索范围。

选择要导入的其他项目

为了尽可能快地导入,以下项目默认不会从 GitHub 导入:

  • 超过约 30,000 条评论,因为 GitHub API 的限制
  • 来自仓库评论、发布帖子、问题描述和拉取请求描述的 Markdown 附件。这些可能包括 图片、文本或二进制附件。如果不导入,从 GitHub 中移除附件后,Markdown 中到附件的链接将失效。

您可以选择导入这些项目,但这可能会显著增加导入时间。要导入这些项目,请在 UI 中选择相应的字段:

  • Use alternative comments import method。如果导入的 GitHub 项目在所有问题和拉取请求中超过约 30,000 条评论,您应该启用此方法,因为 GitHub API 的限制
  • Import Markdown attachments
  • Import collaborators(默认选中)。保持选中可能会导致新用户占用群组或命名空间中的席位, 并被授予 与项目所有者一样高 的权限。仅直接协作者会被导入。 外部协员永远不会被导入。

选择要导入的仓库

默认情况下,建议的仓库命名空间与 GitHub 中存在的名称匹配,但 根据您的权限,您可以在继续导入任何仓库之前选择编辑这些名称。

要选择要导入的仓库,在任意数量的仓库旁边选择 Import 或 选择 Import all repositories

此外,您可以按名称过滤项目。如果应用了过滤器,Import all repositories 只会导入匹配的仓库。

Status 列显示每个仓库的导入状态。您可以选择保持页面 打开并实时查看更新,或者稍后返回。

要取消待处理或正在进行的导入,在导入的项目旁边选择 Cancel。 如果导入已开始,导入的文件将被保留。

要在导入后在 GitLab URL 中打开仓库,选择其 GitLab 路径。

完成的导入可以通过选择 Re-import 并指定新名称来重新导入。这将创建源项目的新副本。

GitHub importer page

检查导入状态

导入完成后,它们可能处于三种状态之一:

  • Complete:GitLab 导入了所有仓库实体。
  • Partially completed:GitLab 未能导入某些仓库实体。
  • Failed:GitLab 在发生关键错误后中止了导入。

展开 Details 查看导入失败的 仓库实体 列表。

用户名提及

GitLab 在问题、合并请求和笔记中为用户名提及添加反引号。 这些反引号防止链接到 GitLab 实例上具有相同用户名的错误用户。

用户贡献和成员映射

GitHub 导入器使用 改进的方法 来映射 GitLab.com 和 GitLab Self-Managed 的用户贡献。

旧的用户贡献映射方法

您可以使用旧的用户贡献映射方法导入到 GitLab Self-Managed 和 GitLab Dedicated 实例。 要使用此方法,必须禁用 github_user_mapping。 对于导入到 GitLab.com,您必须使用 改进的方法

使用旧方法时,当 用户账户正确配置 时,用户会在导入期间被映射。

如果不满足要求,导入器无法映射特定用户的贡献。在这种情况下:

  • 项目创建者被设置为问题和合并请求的作者和被指派人。项目创建者通常是 启动导入过程的用户。对于某些有描述或笔记的贡献(如拉取请求、问题、笔记), 导入器会修改文本,添加谁最初创建贡献的详细信息。
  • GitHub 中拉取请求上添加的审查者和批准无法导入。在这种情况下,导入器会创建 描述不存在的用户被添加为审查者和批准者的评论。但是,实际的审查者状态和 批准不会应用到 GitLab 中的合并请求。

镜像仓库并共享管道状态

  • Tier: Premium, Ultimate

根据您的 GitLab 层级,可以设置 仓库镜像 以保持 您的导入仓库与其 GitHub 副本同步。

此外,您可以配置 GitLab 通过 GitHub 项目集成 将管道状态更新发送回 GitHub。

如果您使用 外部仓库的 CI/CD 导入您的项目, 则这两个功能会自动配置。

镜像不会同步您的 GitHub 项目中的任何新或更新的拉取请求。

提高 GitLab Self-Managed 实例上的导入速度

这些步骤需要 GitLab 服务器上的管理员访问权限。

增加 Sidekiq 工作进程的数量

对于大型项目,导入所有数据可能需要一些时间。为了减少所需时间,您可以增加处理以下队列的 Sidekiq 工作进程数量:

  • github_importer
  • github_importer_advance_stage

为了获得最佳体验,建议至少有 4 个 Sidekiq 进程(每个进程运行与 CPU 核心数量相等的线程数), 仅处理这些队列。还建议这些进程在单独的服务器上运行。对于 4 台 8 核服务器,这意味着您可以并行导入 最多 32 个对象(例如,问题)。

通过增加存储 Git 仓库(您的 GitLab 实例)的磁盘的网络吞吐量、CPU 能力和磁盘性能(例如使用高性能 SSD), 可以减少克隆仓库所花费的时间。增加 Sidekiq 工作进程的数量不会减少克隆仓库所花费的时间。

使用 GitHub Enterprise Cloud OAuth App 启用 GitHub OAuth

如果您属于 GitHub Enterprise Cloud 组织,您可以配置 GitLab Self-Managed 以获得更高的 GitHub API 速率限制

GitHub API 请求通常受到每小时 5,000 次请求的速率限制限制。使用以下步骤,您将获得更高的 15,000 次请求/小时的速率限制,从而实现更快的整体导入时间。

先决条件:

要启用更高的速率限制:

  • 在 GitHub 中创建 OAuth 应用。确保 OAuth 应用由 Enterprise Cloud 组织拥有,而不是您的个人 GitHub 账户。
  • 使用 GitHub OAuth 执行项目导入。
  • 可选。默认情况下,所有配置的 OAuth 提供者都启用了登录。 如果您希望为导入启用 GitHub OAuth,但希望 防止用户使用 GitHub 登录到您的 GitLab 实例, 您可以 禁用使用 GitHub 登录

导入的数据

项目的以下项目被导入:

对拉取请求和问题的引用被保留。每个导入的仓库保持可见性级别,除非该 可见性级别受到限制,在这种情况下 默认为默认项目可见性。

分支保护规则和项目设置

导入时,支持的 GitHub 分支保护规则被映射到:

  • GitLab 分支保护规则。
  • 项目范围的 GitLab 设置。
GitHub 规则 GitLab 规则 引入于
Require conversation resolution before merging for the project’s default branch All threads must be resolved 项目设置 GitLab 15.5
Require a pull request before merging No one 选项在 Allowed to push and merge 列表中的 分支保护设置 GitLab 15.5
Require signed commits for the project’s default branch Reject unsigned commits GitLab 推送规则 GitLab 15.5
Allow force pushes - Everyone Allowed to force push 分支保护设置 GitLab 15.6
Require a pull request before merging - Require review from Code Owners Require approval from code owners 分支保护设置 GitLab 15.6
Require a pull request before merging - Allow specified actors to bypass required pull requests 分支保护设置Allowed to push and merge 列表中的用户列表。如果没有 Premium 订阅,允许推送和合并的用户列表仅限于角色。 GitLab 15.8

将 GitHub 规则 Require status checks to pass before merging 映射到 外部状态检查 在问题 370948 中被考虑。然而,由于技术困难,此规则在项目导入到 GitLab 时不会被导入。您仍然可以手动创建 外部状态检查

协作者(成员)

这些 GitHub 协作者角色被映射到这些 GitLab 成员角色

GitHub 角色 映射的 GitLab 角色
Read Guest
Triage Reporter
Write Developer
Maintain Maintainer
Admin Owner

GitHub Enterprise Cloud 有 自定义仓库角色。 这些角色不受支持,会导致部分完成的导入。

要导入 GitHub 协作者,您必须在 GitHub 项目上至少拥有 Write 角色。否则协作者导入将被跳过。

从内部网络上的 GitHub Enterprise 导入

如果您的 GitHub Enterprise 实例在无法访问互联网的内部网络上,您可以使用反向代理 允许 GitLab.com 访问该实例。

代理需要:

  • 将请求转发到 GitHub Enterprise 实例。
  • 将内部主机名的所有出现转换为公共代理主机名,在:
    • API 响应体中。
    • API 响应 Link 头中。

GitHub API 使用 Link 头进行分页。

配置代理后,通过发出 API 请求进行测试。以下是一些测试 API 的命令示例:

curl --header "Authorization: Bearer <YOUR-TOKEN>" "https://{PROXY_HOSTNAME}/user"

### 响应体中的 URL 应使用代理主机名

{
  "login": "example_username",
  "id": 1,
  "url": "https://{PROXY_HOSTNAME}/users/example_username",
  "html_url": "https://{PROXY_HOSTNAME}/example_username",
  "followers_url": "https://{PROXY_HOSTNAME}/api/v3/users/example_username/followers",
  ...
  "created_at": "2014-02-11T17:03:25Z",
  "updated_at": "2022-10-18T14:36:27Z"
}
curl --head --header "Authorization: Bearer <YOUR-TOKEN>" "https://{PROXY_DOMAIN}/api/v3/repos/{repository_path}/pulls?states=all&sort=created&direction=asc"

### Link 头应使用代理主机名

HTTP/1.1 200 OK
Date: Tue, 18 Oct 2022 21:42:55 GMT
Server: GitHub.com
Content-Type: application/json; charset=utf-8
Cache-Control: private, max-age=60, s-maxage=60
...
X-OAuth-Scopes: repo
X-Accepted-OAuth-Scopes:
github-authentication-token-expiration: 2022-11-22 18:13:46 UTC
X-GitHub-Media-Type: github.v3; format=json
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4997
X-RateLimit-Reset: 1666132381
X-RateLimit-Used: 3
X-RateLimit-Resource: core
Link: <https://{PROXY_DOMAIN}/api/v3/repositories/1/pulls?page=2>; rel="next", <https://{PROXY_DOMAIN}/api/v3/repositories/1/pulls?page=11>; rel="last"

还要测试使用代理克隆仓库不会失败:

git clone -c http.extraHeader="Authorization: basic <base64 encode YOUR-TOKEN>" --mirror https://{PROXY_DOMAIN}/{REPOSITORY_PATH}.git

示例反向代理配置

以下配置是如何配置 Apache HTTP Server 作为反向代理的示例

为简单起见,该代码段没有包含在客户端和代理之间加密连接的配置。但是,出于安全原因,您应该包含该 配置。请参阅 示例 Apache TLS/SSL 配置

# Required modules
LoadModule filter_module lib/httpd/modules/mod_filter.so
LoadModule reflector_module lib/httpd/modules/mod_reflector.so
LoadModule substitute_module lib/httpd/modules/mod_substitute.so
LoadModule deflate_module lib/httpd/modules/mod_deflate.so
LoadModule headers_module lib/httpd/modules/mod_headers.so
LoadModule proxy_module lib/httpd/modules/mod_proxy.so
LoadModule proxy_connect_module lib/httpd/modules/mod_proxy_connect.so
LoadModule proxy_http_module lib/httpd/modules/mod_proxy_http.so
LoadModule ssl_module lib/httpd/modules/mod_ssl.so

<VirtualHost GITHUB_ENTERPRISE_HOSTNAME:80>
  ServerName GITHUB_ENTERPRISE_HOSTNAME

  # Enables reverse-proxy configuration with SSL support
  SSLProxyEngine On
  ProxyPass "/" "https://GITHUB_ENTERPRISE_HOSTNAME/"
  ProxyPassReverse "/" "https://GITHUB_ENTERPRISE_HOSTNAME/"

  # Replaces occurrences of the local GitHub Enterprise URL with the Proxy URL
  # GitHub Enterprise compresses the responses, the filters INFLATE and DEFLATE needs to be used to
  # decompress and compress the response back
  AddOutputFilterByType INFLATE;SUBSTITUTE;DEFLATE application/json
  Substitute "s|https://GITHUB_ENTERPRISE_HOSTNAME|https://PROXY_HOSTNAME|ni"
  SubstituteMaxLineLength 50M

  # GitHub API uses the response header "Link" for the API pagination
  # For example:
  #   <https://example.com/api/v3/repositories/1/issues?page=2>; rel="next", <https://example.com/api/v3/repositories/1/issues?page=3>; rel="last"
  # The directive below replaces all occurrences of the GitHub Enterprise URL with the Proxy URL if the
  # response header Link is present
  Header edit* Link "https://GITHUB_ENTERPRISE_HOSTNAME" "https://PROXY_HOSTNAME"
</VirtualHost>