> For the complete documentation index, see [llms.txt](https://dev.ppgg.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dev.ppgg.in/contributing/pull-requests/branching.md).

# 分支

{% hint style="info" %}
对应的[官方页面地址](https://contributing.bitwarden.com/contributing/pull-requests/branching/)
{% endhint %}

## 命名约定 <a href="#naming-convention" id="naming-convention"></a>

要保持分支有组织性，我们需要遵守分支的命名约定。

这种命名约定使我们能够轻松识别分支上正在完成的工作类型，并将有助于识别和跟踪过时的分支。

### 特定 Jira 议题的分支 <a href="#branches-for-a-specific-jira-issue" id="branches-for-a-specific-jira-issue"></a>

为了将分支上的工作链接到我们的 Jira 议题，分支名称应由三部分组成，并用斜杠分隔：

* 团队名称或缩写（例如 `vault`），以及
* Jira 议题标签（例如 `pm-1234`）
* 正在完成的工作的简短描述（例如 `update-csp-hashes`）

在此示例中，完整的分支名称为 `vault/pm-1234/update-csp-hashes` 。

* 分支名称中仅使用小写字母。
* 使用 `-` 分隔单词，使用 `/` 分隔分支名称部分。仅使用这些字符来分隔单词或部分。
* 将工作描述部分限制为约 50 个字符。总体分支名称最多应为 80 个字符。
* 团队名称必须一致。要么总是缩写，要么不缩写。

### 多个 Jira 议题的分支​ <a href="#branches-for-multiple-jira-issues" id="branches-for-multiple-jira-issues"></a>

如果分支将包含多个 Jira 议题（很可能是因为它是[长期功能分支](#long-lived-feature-branch)）的工作，则名称应该是功能的描述性名称，用破折号分隔（例如 `my-long-lived-feature`）。尽可能考虑简洁，因为我们的 QA 团队在对功能执行 QA 测试时需要使用此分支名称。

## 分支开发 <a href="#branching-for-development" id="branching-for-development"></a>

分支策略的开发取决于是否使用我们所谓的「长期功能分支」来管理工作。

{% hint style="info" %}
我们在本文档中使用术语「功能」来指代对代码库的任何更改，无论是一组新功能、错误修复还是重构现有代码。这并不意味着要排除本身不是「功能」的开发类型。
{% endhint %}

### 选择哪种分支模型？​ <a href="#which-branching-model-to-choose" id="which-branching-model-to-choose"></a>

分支模型的开发选择取决于您计划如何处理**整体可测试、可发布的功能**。因此，在开始处理一组新的 Jira 故事或任务时应该提前计划，并且需要整个团队（开发、QA 和产品）之间的协调。

如果该功能将满足以下条件，请选择**长期功能分支**：

* 需要多个拉取请求来生成可测试、可发布的更改，并且
* 无法将更改放在功能标志后面。

如果该功能将满足以下条件，请选择**短期功能分支**：

* 需要一个拉取请求来生成可测试、可发布的更改，或者
* 当多个 PR 正在运行时，可以将更改放在功能标志后面。

{% hint style="success" %}
如果有疑问，请倾向于直接从 `master` 为每个开发人员的工作创建短期功能分支，因为长期功能分支会产生内置开销。
{% endhint %}

### 长期功能分支​ <a href="#long-lived-feature-branch" id="long-lived-feature-branch"></a>

当产生最小的独立可测试、可发布变更的工作主体太大而无法封装在单个 PR 中，或者需要多个开发人员的贡献时，长期功能分支是必要的。

长期功能分支应**仅仅**包含：

* 个人对该功能的贡献已批准更改的 PR，以及
* 合并来自 `master` 的提交

任何其他直接提交到长期功能分支都会使 `master` 的最终 PR 的最终审查变得复杂，应该避免。

#### **开发** <a href="#development" id="development"></a>

要开始使用长期功能分支开发某个功能，贡献者应该为该功能创建长期功能分支，并从该分支创建一个草稿 PR 到 `master` 中。如果适用，此名称应包含 Jira Epic 名称。

然后，每个开发人员都应该从该功能分支中分支出来，创建一个以发起 Jira 议题命名的「议题分支」，如[特定 Jira 议题的分支](#branches-for-a-specific-jira-issue)中所述。我们将其称为议题分支，因为 Jira 将故事和任务称为议题，并与上面的长期功能分支区分开来。

{% hint style="info" %}
值得注意的是，在这种情况下，我们决定不能（或不会）独立测试或发布每个问题分支。我们引入了一个中间功能分支来收集所有这些相关更改，以允许作为一个整体进行测试和发布。
{% endhint %}

当每个开发人员完成他们的工作时，他们应该在长期功能分支中打开一个 PR。对长期功能分支的每项更改都必须有经过批准的 PR，否则在最终合并到 `master` 之前，所有这些单独的提交都需要经过审查。开发人员应该标记适当的开发组来审查 PR。

当开发人员批准 PR 时，PR 应完成，并将整体更改的一部分合并到长期功能分支中。

合并所有议题分支后，`needs-qa` 标签应应用于长期功能分支。

#### **同步长期功能分支​** <a href="#syncing-the-long-lived-feature-branch" id="syncing-the-long-lived-feature-branch"></a>

我们通常指定一个人负责使长期功能分支保持最新状态。在大多数情况下，这将是团队的技术主管，但可以是任何人。此人负责使功能分支与 master 保持合理的最新状态，为合并等做好准备。

由于 GitHub 处理审查的方式，此人也无法批准长期功能分支的最终 PR。审查者可以是团队中的任何人。然而，由于该分支的工作通常较大，因此具有代码库的一些资历可能是有益的。

#### **QA** <a href="#qa" id="qa"></a>

QA 团队在长期功能分支上进行测试（请注意，QA 在 PR 完成后进行）。这是因为该流程的前提是功能的各个部分无法单独测试。

如果 QA 发现缺陷，则应在长期功能分支之外的另一个议题分支中修复该缺陷，并在长期功能分支中使用另一个经过审查的 PR 来解决该议题。

#### **最终审查​** <a href="#final-review" id="final-review"></a>

由于每个拉取请求在合并到长期功能分支之前已经经过审查，因此功能分支审查更多的是健全性检查。审查者应确保以下内容：

* 该功能分支已准备好合并到 `master` 中。
  * 确保工作已经过 QA 测试，包括在需要时在 Jira 中编写 QA 注释，或者
  * 验证该功能位于功能标志后面，并且交叉边界经过测试。
* 直接在分支上审查任何未经审查的提交。这些可以是功能工作或合并提交。

{% hint style="danger" %}
由于功能分支没有与主分支相同的保护，因此在技术上可以直接提交到分支或合并拉取请求，而无需进行最新的审查。然而，这不应该鼓励，并且应尽可能避免，唯一的例外是合并提交。
{% endhint %}

当功能分支上的所有开发和功能测试完成后，`master` 中的原始 PR 应移出草稿状态，并用适当的开发组标记它以供审查。

可以使用 GitHub 的 UI 打开 Pull 请求并单击 `Commits` 选项卡来执行最终审查。然后可以单独检查每个提交。

* 通过点击拉取请求链接并验证提交 SHA 哈希匹配，验证提交是否具有现有审查。寻找 `Author merged commit {hash} into branch`。
* 如果不执行提交的定期代码审查。

合并提交也应该进行审查，GitHub UI 将自动简化合并提交并仅显示所做的更改。如果从命令行或通过其他工具进行审查，请使用命令 `git show <hash>`。有关一些背景和更多信息，请阅读[如何审查合并提交](https://haacked.com/archive/2014/02/21/reviewing-merge-commits/)。

### 短期功能分支​ <a href="#short-lived-feature-branch" id="short-lived-feature-branch"></a>

短期功能分支非常适合以下工作主体：

* 可由单个贡献者开发
* 以在单个拉取请求中进行审查
* 可以独立测试，并且
* 可独立发布

对于小部分新功能和大多数错误修复来说，通常都是这种情况。

#### **开发** <a href="#development" id="development"></a>

开发人员应创建一个以发起 Jira 议题命名的分支（例如 `PM-1234`），并从该分支创建草稿 PR 到 `master` 中。

{% hint style="info" %}
分支名称应尽可能短，最好只是议题名称。这使得 QA 团队可以更轻松地将环境切换到各个分支，因为他们在执行此操作时必须多次输入分支名称。这对于短期功能分支尤其重要，其中测试可能要简短得多。
{% endhint %}

开发过程中，应定期将 `master` 分支合并到分支中，以避免冲突。

开发完成后，开发人员应准备 PR 供审查：

* 从 PR 中删除草稿状态
* 将 `needs-qa` 标签添加到 PR
* 如果需要设计批准，则标记适当的开发组以供审查和 `@dept-design`

当团队成员批准 PR 时，它应该保持开放状态以供测试。这很重要，因为此时完成 PR 会向 `master` 引入未经测试的更改。

#### **QA** <a href="#qa" id="qa"></a>

QA 团队应该在短期功能分支上进行测试。如果发现任何缺陷，则应通过直接提交到短期功能分支来解决这些缺陷，从而在重新引入 QA 的新更改之前触发开发人员团队的重新审查。

在 QA 测试了功能并且开发人员解决了所有缺陷后，PR 所有者应完成 PR 并将更改合并到 `master` 分支中。

## **发布分支** <a href="#branching-for-release" id="branching-for-release"></a>

在给定版本的开发完成日期后的第一个工作日，将在 `master` 基础上创建 `rc` 分支。这是 `master` 中正在进行的工作的快照，它将代表即将发布的版本中发布代码。

`rc` 分支用于回归测试。然后将其用作每个已部署实体的生产发布和部署的源。每次发布时，都会创建一个 `vYYYY.MM.#-{component}` 格式的标签。这可用于稍后修复此版本。

发布完成后，`rc` 分支将被删除。

### 修补程序版本​ <a href="#hotfix-releases" id="hotfix-releases"></a>

对于修补程序版本，会根据应应用修补程序的版本的版本标记创建修补程序分支。分支命名取决于存储库。对于除 `clients` 之外的所有存储库，分支名称为 `hotfix-rc`。但是，由于我们可以单独发布各个客户端，因此 `clients` 存储库中的每个客户端都有自己的已命名修补程序分支：

* 网页端： `hofix-rc-web`
* 桌面端： `hotfix-rc-desktop`
* 浏览器端： `hotfix-rc-browser`
* CLI： `hotfix-rc-cli`

创建修补程序分支后，`master` 中的各个提交将被精心挑选到修补程序分支中。对于客户端修复，这可能需要挑选多个修补程序分支。

部署修补程序后，修补程序分支将被删除。

{% hint style="success" %}
**修补程序 QA 测试**

对于修补程序，在合并到 `master` 之前，我们不会对功能分支执行 QA 测试。这是我们承认的风险，为了加快修补程序过程并避免必须切换所有 QA 测试环境以引用我们的修补程序分支。

相反，一旦 PR 获得批准，修补程序更改就会合并到 `master` 中，然后精心挑选到适当的修补程序分支。然后在修补程序分支上对它们进行测试。
{% endhint %}
