# 分支

{% 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.ppgg.in/contributing/pull-requests/branching.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
