# 将数据迁移到 GitHub Enterprise Server

生成迁移存档后，可以将数据导入目标 GitHub Enterprise Server 实例。 在将变更永久应用到目标实例之前，您需要检查变更，查看有无潜在的冲突。

## 准备要迁移的数据

1. [
   `scp`
   ](https://acloudguru.com/blog/engineering/ssh-and-scp-howto-tips-tricks#scp)使用此命令，将从源实例或组织生成的迁移存档复制到GitHub Enterprise Server目标：

   ```shell
   scp -P 122 PATH-TO-MIGRATION-GUID.tar.gz admin@HOSTNAME:/home/admin/
   ```

2. 通过 SSH 连接到目标 GitHub Enterprise Server 实例。 有关详细信息，请参阅“[访问管理 shell (SSH)](/zh/enterprise-server@3.22/admin/administering-your-instance/administering-your-instance-from-the-command-line/accessing-the-administrative-shell-ssh)”。

   ```shell
   ssh -p 122 admin@HOSTNAME
   ```

3. 确保迁移存档有足够的读取权限。

   ```shell
   chmod 644 /home/admin/MIGRATION-GUID.tar.gz
   ```

4. 使用 `ghe-migrator prepare` 命令准备要在目标实例上导入的存档，并生成新的迁移 GUID 供你在后续步骤中使用：

   ```shell
   ghe-migrator prepare /home/admin/MIGRATION-GUID.tar.gz
   ```

   * 若要启动新的导入尝试，请再次运行 `ghe-migrator prepare` 并获取新的迁移 GUID。
   * 要指定迁移文件的暂存位置，请在命令后附加 `--staging-path=/full/staging/path`。 默认为 `/data/user/tmp`。

## 生成迁移冲突列表

1. 将 `ghe-migrator conflicts` 命令与迁移 GUID 配合使用，生成 conflicts.csv 文件：

   ```shell
   ghe-migrator conflicts -g MIGRATION-GUID > conflicts.csv
   ```

   * 如果未报告任何冲突，则可以安全地导入数据。

2. 如果存在冲突，请使用 [`scp`](https://acloudguru.com/blog/engineering/ssh-and-scp-howto-tips-tricks#scp) 命令将 conflicts.csv 复制到本地计算机：

   ```shell
   scp -P 122 admin@HOSTNAME:conflicts.csv ~/Desktop
   ```

3. 继续执行[解决迁移冲突或设置自定义映射](#resolving-migration-conflicts-or-setting-up-custom-mappings)。

## 审查迁移冲突

1. 使用文本编辑器或者[与 CSV 兼容的电子表格软件](https://en.wikipedia.org/wiki/Comma-separated_values#Application_support)，打开 conflicts.csv。
2. 根据下方示例和参考表的指导，检查 conflicts.csv 文件，以确保在导入时能够正确执行操作。

conflicts.csv 文件包含冲突的迁移映射和建议操作。 迁移映射列出了数据的迁移来源和数据应用到目标的方式。

| `model_name`   | `source_url`                                           | `target_url`                                           | `recommended_action` |
| -------------- | ------------------------------------------------------ | ------------------------------------------------------ | -------------------- |
| `user`         | `https://example-gh.source/octocat`                    | `https://example-gh.target/octocat`                    | `map`                |
| `organization` | `https://example-gh.source/octo-org`                   | `https://example-gh.target/octo-org`                   | `map`                |
| `repository`   | `https://example-gh.source/octo-org/widgets`           | `https://example-gh.target/octo-org/widgets`           | `rename`             |
| `team`         | `https://example-gh.source/orgs/octo-org/teams/admins` | `https://example-gh.target/orgs/octo-org/teams/admins` | `merge`              |

conflicts.csv 中的每一行都提供了以下信息：

| 名称                   | 说明                             |
| -------------------- | ------------------------------ |
| `model_name`         | 数据类型的更改。                       |
| `source_url`         | 数据的源 URL。                      |
| `target_url`         | 数据的预计目标网址。                     |
| `recommended_action` | 导入数据时 `ghe-migrator` 将执行的首选操作。 |

### 每个记录类型的可能映射

转移数据时，`ghe-migrator` 可以执行多种不同的映射操作：

| `action`        | 说明                                                          | 适用的模型    |
| --------------- | ----------------------------------------------------------- | -------- |
| `import`        | （默认）源中的数据将导入目标。                                             | 所有记录类型   |
| `map`           | 使用目标中的现有记录，而不是基于源数据创建新模型。 用于将存储库导入现有组织或将目标中的用户标识映射到源中的用户标识。 | 用户、组织    |
| `rename`        | 源中的数据将重命名，然后复制到目标。                                          | 用户、组织和仓库 |
| `map_or_rename` | 如果存在目标，请映射到该目标。 否则，请重命名导入的模型。                               | 用户       |
| `merge`         | 源中的数据将与目标中的现有数据合并。                                          | Teams    |

强烈建议查看 conflicts.csv 文件，并使用 \_\_ 来确保执行适当的操作。 如果一切正常，可以继续。

## 解决迁移冲突或设置自定义映射

如果你认为 `ghe-migrator` 将做出错误的修改，可以通过更改 *conflicts.csv* 中的数据来进行修正。 可以更改 conflicts.csv 中的任意行。

例如，假设你注意到源中的 `octocat` 用户正映射到目标上的 `octocat`。

| `model_name` | `source_url`                        | `target_url`                        | `recommended_action` |
| ------------ | ----------------------------------- | ----------------------------------- | -------------------- |
| `user`       | `https://example-gh.source/octocat` | `https://example-gh.target/octocat` | `map`                |

您可以选择将用户映射到目标上的其他用户。 假设你知道 `octocat` 实际上应该是位于目标上的 `monalisa`。 你可以更改 `target_url` 中的 \_\_ 列以引用 `monalisa`。

| `model_name` | `source_url`                        | `target_url`                         | `recommended_action` |
| ------------ | ----------------------------------- | ------------------------------------ | -------------------- |
| `user`       | `https://example-gh.source/octocat` | `https://example-gh.target/monalisa` | `map`                |

再举一个例子，如果要在目标实例上将 `octo-org/widgets` 存储库重命名为 `octo-org/amazing-widgets`，请将 `target_url` 更改为 `octo-org/amazing-widgets`，将 `recommend_action` 更改为 `rename`。

| `model_name` | `source_url`                                 | `target_url`                                         | `recommended_action` |
| ------------ | -------------------------------------------- | ---------------------------------------------------- | -------------------- |
| `repository` | `https://example-gh.source/octo-org/widgets` | `https://example-gh.target/octo-org/amazing-widgets` | `rename`             |

### 添加自定义映射

迁移过程中一个常见的情况是，迁移用户的用户名在目标上与在源上不同。

如果拥有源中的用户名列表和目标上的用户名列表，您可以通过自定义映射构建一个 CSV 文件，然后应用此文件，确保迁移结束时每个用户的用户名和内容都有正确的映射。

可以使用 `ghe-migrator audit` 命令，以 CSV 格式快速生成应用自定义映射所需的正在迁移的用户的 CSV：

```shell
ghe-migrator audit -m user -g MIGRATION-GUID > users.csv
```

现在，你可以编辑该 CSV，并为你想要映射或重命名的每个用户输入新 URL，然后根据需要将第四列更新为包含 `map` 或 `rename`。

例如，若要在目标 `octocat` 上将用户 `monalisa` 重命名为 `https://example-gh.target`，需创建包含以下内容的行：

| `model_name` | `source_url`                        | `target_url`                         | `state`  |
| ------------ | ----------------------------------- | ------------------------------------ | -------- |
| `user`       | `https://example-gh.source/octocat` | `https://example-gh.target/monalisa` | `rename` |

可以使用相同的流程为支持自定义映射的每个记录创建映射。 有关详细信息，请参阅[有关记录的可能映射的表](#possible-mappings-for-each-record-type)。

### 应用修改的迁移数据

1. 进行更改后，使用 [`scp`](https://acloudguru.com/blog/engineering/ssh-and-scp-howto-tips-tricks#scp) 命令将修改后的 conflicts.csv（或具有正确格式的任何其他映射 .csv 文件）应用于目标实例：

   ```shell
   scp -P 122 ~/Desktop/conflicts.csv admin@HOSTNAME:/home/admin/
   ```

2. 使用 `ghe-migrator map` 命令重新映射迁移数据，传入所修改的 *.csv* 文件路径和迁移 GUID：

   ```shell
   ghe-migrator map -i conflicts.csv -g MIGRATION-GUID
   ```

3. 如果 `ghe-migrator map -i conflicts.csv -g MIGRATION-GUID` 命令报告冲突仍然存在，请再次运行迁移冲突解决过程。

## 将导入的数据应用到GitHub Enterprise Server上

1. 通过 SSH 连接到目标 GitHub Enterprise Server 实例。 有关详细信息，请参阅“[访问管理 shell (SSH)](/zh/enterprise-server@3.22/admin/administering-your-instance/administering-your-instance-from-the-command-line/accessing-the-administrative-shell-ssh)”。

   ```shell
   ssh -p 122 admin@HOSTNAME
   ```

2. 使用 `ghe-migrator import` 命令启动导入过程。 您会需要：

   * 迁移 GUID。 有关详细信息，请参阅[准备迁移数据以导入到 GitHub Enterprise Server](#preparing-the-migrated-data)。
   * 你用于身份验证的 personal access token。 你使用的 personal access token 仅用于以站点管理员身份进行身份验证，不需要任何特定的作用域或权限。 有关详细信息，请参阅“[管理个人访问令牌](/zh/enterprise-server@3.22/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)”。

   ```shell
   $ ghe-migrator import /home/admin/MIGRATION-GUID.tar.gz -g MIGRATION-GUID -u USERNAME -p TOKEN

   > Starting GitHub::Migrator
   > Import 100% complete /
   ```

   * 要指定迁移文件的暂存位置，请在命令后附加 `--staging-path=/full/staging/path`。 默认为 `/data/user/tmp`。

## 检查迁移数据

默认情况下，`ghe-migrator audit` 返回每条记录。 它还可以让您按以下方式筛选记录：

* 记录的类型。
* 记录的状态。

记录类型与[迁移数据](/zh/enterprise-server@3.22/migrations/using-ghe-migrator/about-ghe-migrator#migrated-data)中的记录类型相匹配。

## 记录类型筛选器

| 记录类型           | 筛选器名称                         |
| -------------- | ----------------------------- |
| 用户             | `user`                        |
| 组织             | `organization`                |
| 存储库            | `repository`                  |
| Teams          | `team`                        |
| 里程碑            | `milestone`                   |
| 问题             | `issue`                       |
| 问题评论           | `issue_comment`               |
| 拉取请求           | `pull_request`                |
| 拉取请求审查         | `pull_request_review`         |
| 提交注释           | `commit_comment`              |
| 拉取请求审查评论       | `pull_request_review_comment` |
| 发布             | `release`                     |
| 在拉取请求或问题上进行的操作 | `issue_event`                 |
| 受保护的分支         | `protected_branch`            |

## 记录状态筛选器

| 记录状态            | 说明          |
| --------------- | ----------- |
| `export`        | 记录将被导出      |
| `import`        | 将导入记录。      |
| `map`           | 将映射记录。      |
| `rename`        | 将重命名记录。     |
| `merge`         | 记录将被合并      |
| `exported`      | 已成功导出记录。    |
| `imported`      | 已成功导入记录。    |
| `mapped`        | 已成功映射记录。    |
| `renamed`       | 已成功重命名记录。   |
| `merged`        | 已成功合并记录。    |
| `failed_export` | 记录导出失败。     |
| `failed_import` | 记录导入失败。     |
| `failed_map`    | 记录映射失败。     |
| `failed_rename` | 记录的重命名操作失败。 |
| `failed_merge`  | 记录合并失败。     |

## 筛选已审计的记录

通过 `ghe-migrator audit` 命令，可以使用 `-m` 标志根据记录类型进行筛选。 同样，可以使用 `-s` 标志筛选导入状态。 命令如下所示：

```shell
ghe-migrator audit -m RECORD_TYPE -s STATE -g MIGRATION-GUID
```

例如，要查看每个成功导入的组织和团队，您可以输入：

```shell
$ ghe-migrator audit -m organization,team -s mapped,renamed -g MIGRATION-GUID
> model_name,source_url,target_url,state
> organization,https://gh.source/octo-org/,https://ghe.target/octo-org/,renamed
```

**我们强烈建议审核所有失败的导入。** 为此，你将输入：

```shell
$ ghe-migrator audit -s failed_import,failed_map,failed_rename,failed_merge -g MIGRATION-GUID
> model_name,source_url,target_url,state
> user,https://gh.source/octocat,https://gh.target/octocat,failed
> repository,https://gh.source/octo-org/octo-project,https://ghe.target/octo-org/octo-project,failed
```

如果对导入失败有任何疑问，可以通过访问 [GitHub Enterprise 支持](https://support.github.com)与我们联系。

## 在 GitHub Enterprise Server 上完成导入

在将迁移应用到目标实例并审查迁移后，您需要解锁代码库并将它们从源实例中删除。 我们建议等待两周再删除您的源数据，以便确保所有数据都能按预期运行。

## 在目标实例上解锁仓库

1. 通过 SSH 连接到 你的 GitHub Enterprise Server 实例。 如果实例包含多个节点，例如，如果配置了高可用性或异地复制，则通过 SSH 连接到主节点。 如果使用群集，则可以通过 SSH 连接到任何节点。 将 HOSTNAME 替换为实例的主机名，或节点的主机名或 IP 地址。 有关详细信息，请参阅“[访问管理 shell (SSH)](/zh/enterprise-server@3.22/admin/administering-your-instance/administering-your-instance-from-the-command-line/accessing-the-administrative-shell-ssh)”。

   ```shell copy
   ssh -p 122 admin@HOSTNAME
   ```
2. 使用 `ghe-migrator unlock` 命令解锁所有导入的存储库。 您将需要迁移 GUID：

```shell
$ ghe-migrator unlock -g MIGRATION-GUID
> Unlocked octo-org/octo-project
```

> \[!WARNING]
> 如果存储库包含使用触发器的GitHub Actions`schedule`工作流，则导入后不会自动运行工作流。 若要再次启动计划的工作流，请向存储库推送一个提交。 有关详细信息，请参阅“[触发工作流的事件](/zh/enterprise-server@3.22/actions/reference/workflows-and-actions/events-that-trigger-workflows#schedule)”。

## 在源代码中解锁仓库

迁移完成后，应在源上解锁仓库。

### 在 GitHub.com 上解锁组织的存储库

若要解锁组织中的存储库GitHub.com，需要向`DELETE`发送[](/zh/rest/migrations#unlock-an-organization-repository)请求。 您会需要：

* 用于身份验证的访问令牌
* 迁移的唯一 `id`
* 要解锁的仓库的名称

```shell
curl -H "Authorization: Bearer GITHUB_ACCESS_TOKEN" -X DELETE \
  -H "Accept: application/vnd.github.wyandotte-preview+json" \
  https://api.github.com/orgs/ORG-NAME/migrations/ID/repos/REPO_NAME/lock
```

### 从 GitHub.com 上的组织中删除存储库

解锁 GitHub.com 组织的存储库后，应删除以前使用 [存储库删除终结点](/zh/enterprise-server@3.22/rest/repos/repos#delete-a-repository)迁移的每个存储库。 您需要用于身份验证的访问令牌：

```shell
curl -H "Authorization: Bearer GITHUB_ACCESS_TOKEN" -X DELETE \
  https://api.github.com/repos/ORG-NAME/REPO_NAME
```

### 从 GitHub Enterprise Server 实例中解锁存储库

1. 通过 SSH 连接到 你的 GitHub Enterprise Server 实例。 如果实例包含多个节点，例如，如果配置了高可用性或异地复制，则通过 SSH 连接到主节点。 如果使用群集，则可以通过 SSH 连接到任何节点。 将 HOSTNAME 替换为实例的主机名，或节点的主机名或 IP 地址。 有关详细信息，请参阅“[访问管理 shell (SSH)](/zh/enterprise-server@3.22/admin/administering-your-instance/administering-your-instance-from-the-command-line/accessing-the-administrative-shell-ssh)”。

   ```shell copy
   ssh -p 122 admin@HOSTNAME
   ```
2. 使用 `ghe-migrator unlock` 命令解锁所有导入的存储库。 您将需要迁移 GUID：

```shell
$ ghe-migrator unlock -g MIGRATION-GUID
> Unlocked octo-org/octo-project
```