# 对文档进行版本控制

GitHub Docs 使用 YAML 前辅文和 Liquid 运算符通过单一源方法支持 GitHub 的多个版本。

在 GitHub Docs 上，我们提供的文档版本反映了 GitHub 主要产品/服务在 UI 和功能方面的差异。 参与者可以使用版本控制语法将内容范围限定为特定的产品/服务。

通过版本控制语法，读者可以手动选择适用于他们正在使用的产品的文档版本。 GitHub Docs 的 URL 还可以包括版本控制信息，这允许从一个版本的 GitHub Docs 链接到另一个版本，从而直接向读者显示他们正在使用的产品的相关文档。

## 如何以及在哪里进行版本控制

GitHub Docs 上的内容的版本控制是单一源，可避免重复并保留散文 [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)。 对于文章，将版本控制应用于具有 YAML 元数据的单个 Markdown 文件，然后使用文件散文中的条件语句指示网站根据读者选择的版本显示哪些文本。 单一源与创建反映每个内容版本的单独文件形成鲜明对比。

GitHub Docs 有两种类型的版本控制语法。

* YAML：通常在 `content/` 的 Markdown 文件中的 YAML 前端使用，但也在 `data/` 的许多 YAML 文件类型中使用。 指示整个内容段的版本控制。

  ```yaml
  versions:
    PRODUCT: 'VERSIONS'
    PRODUCT: 'VERSIONS'
    ...
  ```

  以下示例显示了免费、专业和团队版内容，以及 GitHub Enterprise Server 的所有版本。

  ```yaml
  versions:
    fpt: *
    ghes: *
  ```

* Liquid：在 `content/` 和 `data/reusables/` 的 Markdown 文件中使用，在 `data/variables/` 的 YAML 文件中的变量字符串或 `data/glossaries/external.yml` 的字符串中使用。 指示当读者为具有 YAML 前辅文定义的多个版本的内容选择版本时，应显示哪些文本。

  * 基于产品的版本控制：

    ```javascript
    {% ifversion SHORT-PRODUCT-NAME %} ... {% endif %}
    ```

  * 基于功能的版本控制：

    ```javascript
    {% ifversion FEATURE-NAME %} ... {% endif %}
    ```

## 关于 GitHub 的不同版本

我们为 GitHub 计划用户提供带版本控制的文档，包括 GitHub Enterprise Cloud 和 GitHub Enterprise Server。 如果网站上存在多个页面版本，读者可以从页面顶部的版本选取器中选择版本。

### GitHub.com

GitHub.com 文档有两个可能的版本：

#### 免费、专业或团队计划

对于 GitHub.com 上的免费、专业或团队计划，请使用 `free-pro-team@latest`。 短名称为 `fpt`。

#### GitHub Enterprise Cloud

对于 GitHub Enterprise Cloud，请使用 `enterprise-cloud@latest`。 短名称为 `ghec`。

### GitHub Enterprise Server

GitHub Enterprise Server 的文档有多个版本，可以分为两种类型：\_支持的版本\_文档（我们同时支持四个版本）和 \_关闭 版本\_文档（我们不会在 Docs 站点上链接到这些版本，但永久支持这些文档的“冻结”照快，因此，如果你知道 URL，那么你仍然可以访问它们。 有关列表，请参阅 [`lib/enterprise-server-releases.ts`](https://github.com/github/docs/blob/main/src/versions/lib/enterprise-server-releases.ts)。

版本名为 `enterprise-server@<release>`。 短名称为 `ghes`。 在 Liquid 条件中，我们可以指定范围，如 `ghes > 3.0`。 有关详细信息，请参阅[使用 Liquid 条件运算符进行版本控制](#versioning-with-liquid-conditional-operators)。

## YAML 前辅文中的版本控制

可以使用文件前辅文中的 `versions` 属性来定义文章将显示的产品。 索引文件需要 `versions` 属性，但它们将根据子级的版本自动进行版本控制。

例如，以下 YAML 前辅文将对 GitHub Enterprise Server 2.20 及更高版本以及免费、专业或团队版的文章进行版本控制。

```yaml
title: About your personal dashboard
versions:
  fpt: '*'
  ghes: '>=2.20'
```

以下示例将针对所有受支持的 GitHub Enterprise Server 版本的文章进行版本控制：

```yaml
title: Downloading your license
versions:
  ghes: '*'
```

还可对一系列发布的页面进行版本控制。 以下示例将仅对免费版、专业版和团队版、GitHub Enterprise Cloud 和 GitHub Enterprise Server 版本 3.1 和 3.2 的页面进行版本控制：

```yaml
versions:
  fpt: '*'
  ghec: '*'
  ghes: '>=3.1 <3.3'
```

## 使用 Liquid 条件运算符进行版本控制

我们使用 [Liquid 模板语言](https://shopify.github.io/liquid/basics/introduction/)（特别是[这个 Node.js 端口](https://github.com/harttle/liquidjs)）和自定义 `{% ifversion ... %}` 标记来创建文档版本。

如果在页面的 YAML 前辅文的 `versions` 键中定义多个产品，则可以使用 Markdown 中的条件运算符 `ifversion`/`else`（或 `ifversion`/`elsif`/`else`）来控制网站如何在页面上呈现特定产品的内容。 例如，功能在 GitHub.com 上可能具有比 GitHub Enterprise Server 更多的选项，因此可以通过 `versions` 前辅文适当地对内容进行版本控制，并使用 Liquid 条件描述 GitHub.com 的其他选项。

> \[!NOTE]
>
> * 对基于产品的版本控制和`ifversion`使用 [](#about-feature-based-versioning)。
> * 不要使用 `if` 或 `unless`。
> * 确保使用 `elsif` 而不是 `else if`。 Liquid 无法识别 `else if` 并且不会在 `else if` 块内呈现内容。

### 比较运算符

对于没有编号的版本（如 `fpt` 和 `ghec`），有两个选项：

* `{% ifversion ghec %}`
* `{% ifversion not ghec %}`

对于具有编号的版本（当前只有 `ghes`），可以对所有版本中可用或未在任何版本中提供的内容执行相同操作：

* `{% ifversion ghes %}`
* `{% ifversion not ghes %}`

如果需要表示仅在某些版本中可用（或不可用）的内容，可以使用以下运算符：

| 操作员                                          | 含义     | 示例                           |
| -------------------------------------------- | ------ | ---------------------------- |
| `=`                                          | 等于     | `{% ifversion ghes = 3.0 %}` |
| `>`                                          | 新于     | `{% ifversion ghes > 3.0 %}` |
| `<`                                          | 保留时间超过 | `{% ifversion ghes < 3.0 %}` |
| `!=`                                         | 不等于    |                              |
| `{% ifversion ghes != 3.0 %}`（不在范围内使用 `not`） |        |                              |

GitHub Docs 不支持 Liquid 运算符 `==`、`>=` 和 `<=`。

### 逻辑运算符

当所有操作数都必须为 true 才能使条件为 true 时，请使用运算符 `and`：

```text
{% ifversion ghes > 2.21 and ghes < 3.1 %}
```

当至少一个操作数必须为 true 才能使条件为 true 时，请使用运算符 `or`：

```text
{% ifversion fpt or ghes > 2.21 %}
```

请勿使用运算符 `&&` 或 `||`。 Liquid 无法识别它们，并且内容不会在预期版本中呈现。

### 空格控制

当在列表中使用 Liquid 条件时，可以使用[空格控制](https://shopify.github.io/liquid/basics/whitespace/)字符来防止添加新行以及可能破坏列表渲染的其他空格。

您可以在左侧、右侧或两侧添加连字符 (`-`)，来表明该侧不应有新行或其他空格。

```text
{%- ifversion fpt %}
```

例如，若要对程序的一个步骤进行版本控制，而不为从前一步骤结尾起始的步骤添加 Liquid 版本控制，如下所示：

```markdown
1. This step is for all versions{% ifversion ghes %}
1. This step is for GHES only{% endif %}
1. This step is for all versions
```

你可以在单独行包含 Liquid 版本控制，并使用空格控制来剥离左侧新行的 Liquid 标签。 这样做可简化源读取，而不破坏列表渲染：

```markdown
1. This step is for all versions
{%- ifversion ghes %}
1. This step is for GHES only
{%- endif %}
1. This row is for all versions
```

## 关于基于功能的版本控制

记录任何新的更改或功能时，请使用基于功能的版本控制。

少数功能和更改将仅应用于一个产品。 大多数功能都来自 GitHub.com，并最终应用于所有产品。 通常，“流”从 GitHub.com（包括 GitHub Enterprise Cloud）更改[为 GitHub Enterprise Server](/zh/enterprise-server@3.22/admin/overview/about-upgrades-to-new-releases)。

基于功能的版本控制提供命名的“功能标志”，可简化文档的维护和版本控制。 可以使用单个功能名称（或“标志”）来对内容中的散文进行分组和版本控制。 当某个功能涉及其他产品时，只需更改 `data/features/` 中文件中的 YAML 版本控制。

### 管理功能

每项功能都通过 `data/features/` 中的单个 YAML 文件进行管理。

> \[!NOTE]
> 请勿删除 `data/features/placeholder.yml`，因为测试将用到它。

若要创建新功能，请先创建一个新的 YAML 文件，其中包含要在此目录中使用的功能名称。 对于命名 `meow` 的功能，它将为 `data/features/meow.yml`。

在 YAML 文件中添加一个 `versions` 块，其中带有该功能所提供的版本的短名称。 举例来说：

```yaml
versions:
  fpt: '*'
  ghec: '*'
  ghes: '>3.1'
```

格式和允许的值与 frontmatter 版本属性相同。 有关详细信息，请参阅 [](https://github.com/github/docs/tree/main/content#versions) 存储库自述文件中的`github/docs`。

### Liquid 条件

你现在可以在内容文件中使用 `{% ifversion meow %} ... {% endif %}`！

### 前辅文

还可以在内容文件的前辅文中使用该功能：

```yaml
versions:
  feature: 'meow'
```

只能使用一个 `feature` 下的一个 `versions` 项，值 `feature` 只能包含一个功能名称。

可以在 frontmatter 中合并基于功能的版本控制和标准版本控制。 执行此操作时，本文将包含在基于功能的版本控制文件中指定的所有版本的超集中，并且直接包含在 Markdown 文件中。 例如，你可能具有目前仅在 GHEC 中可用的功能，并在基于功能的版本控制中指定此功能。 但是，你希望此功能的“关于”文章在 FPT 文档中也可见。在此情况下，你可以将 `fpt` 和 `feature` 添加到前面的 `versions` 块中：

```yaml
versions:
  fpt: '*'
  feature: 'some-new-feature'
```

## 最佳做法

进行版本控制的内容会影响读者，还会影响参与或审阅内容的任何人。 下面是一些提示，可改进版本控制语法的编写、阅读和审阅体验。 这些做法都不是强制性的，你会发现一些例外情况，但它们旨在作为有用的启发式方法来帮助你思考版本控制。

### 避免不必要的版本控制

对于读者来说，获得一般的理解比阅读准确反映特定产品或计划之间差异的详细信息更重要。 在概念性或过程性内容中，尝试以不需要版本控制语法的常规方式描述 UI 的功能或部分。 除了更易于维护外，还增强了读者对参考多个产品文档的理解。

* 问下自己，“我是否可以在不进行任何版本控制的情况下以适用于所有产品的方式编写此内容？”
* 如果可以，请尽量避免对屏幕截图进行版本控制，因为创建它们需要花费精力。 UI 复制之间的细微差异不会影响理解。 如果存在特定于产品的文本或 UI 元素，但屏幕截图仍提供有用的上下文，请问问自己，对屏幕截图进行版本控制是否会在一定程度上影响理解。
* 如果你可以解释一个概念或引导读者完成一个过程，而无需对特定产品进行版本控制，则不要对散文进行版本控制。

### 修改现有内容文件时，请尽早并经常性地查看现有版本控制

保持对现有版本控制的认识将有助于确保编写相关的版本控制语句，并有助于提醒你准确对新内容进行版本控制。

* 开始编辑时，务必在前辅文中查看整个页面的版本控制。
* 围绕正在编辑的内容查看版本控制。
* 查看所做更改的呈现版本，并切换到页面的每个可用版本，作为自我评审的一部分。

### 尽可能避免重复

在句子或段落中使用版本控制语法来区分两种不同计划或产品的散文。 参与者可以使用版本控制语句仅编辑一个段落，而无需考虑较大的版本控制文本块，并在两个位置修改相似但版本不同的散文。 审阅者可以一次提出更改建议，而无需在多个位置留下相同的建议。 但是，如果句子或段落中的行为差异很大或版本控制对参与者而言变得复杂或难以分析，请考虑重复自己的工作，使散文更易于维护。

* 在段落中使用内联版本控制语法，以避免重复句子或整个段落。

  > 可以执行{% ifversion fpt %}某些操作{% elsif ghec %}其他操作{% endif %}。

* 使用判断：对于在句子或段落中没有大量版本控制语法的情况下难以编写或阅读的散文，请考虑在每个相关产品的版本块中重复整个段落。

  > {% ifversion fpt %}
  >
  > 如果使用免费、专业或团队计划，则可以执行某些操作。 下面是有关可以使用免费、专业或团队计划执行的操作的详细信息...
  >
  > {% elsif ghec %}
  >
  > 如果使用 GitHub Enterprise Cloud，则可以执行其他操作。 下面是有关可以使用 GitHub Enterprise Cloud 执行的操作的详细信息...
  >
  > {% endif %}

### 显式，而不是隐式

如果确切地知道内容所描述的产品，请对这些产品进行显式版本控制。
`not` 之类的语法（尤其是 `else`）可能不精确。
`not` 和 `else` 的最终结果取决于每篇文章的前辅文，因此参与者必须做更多的调查，以了解使用此版本控制的散文。 这可能会产生错误。 在可重用中，隐式版本控制的复杂性会增加，其中引用可重用的文章可能具有不同的版本控制，因此对 `not` 或 `else` 的计算不同。 当 GitHub Docs 引入新产品时，我们偶尔也会向 GitHub 引入新版本，当我们将新版本添加到现有文章中时，这会改变 `not` 和 `else` 的最终结果。

* 请记住，GitHub 提供四种产品，并且 GitHub Docs 可以在任何给定时间显示总共 8 个版本的文档。
* 在开始编辑时，请仔细查看前辅文中整篇文章的版本控制，因为这有助于你了解 Liquid 语句中 `not` 和 `else` 的行为方式，或者当你在前辅文中启用新版本时，它们是如何变化的。

### 在完成内容设计和创建时验证和沟通版本控制

有时，更改不会包含在最初打算应用的版本中。 可以通过在整个内容设计和创建过程中确认版本控制，为发布和改进节省审阅者的时间，并确保内容更准确。

* 在内容设计中考虑版本控制，并在请求利益干系人对内容创建进行评审时对版本控制进行双重检查。
* 让其他作者和利益干系人更轻松地进行评审：指出请求评审的版本之间的差异，并在必要时链接到内容的特定呈现版本。
* 信任但验证。

### 测试、测试和再次测试

无论是编写还是审阅内容，都要注意内容设计计划和受影响的产品，并在过渡或开发环境中检查呈现的内容，以确保内容准确地描述每个产品。