

亚马逊 CodeCatalyst 不再向新买家开放。现有客户可以继续正常使用该服务。有关更多信息，请参阅 [如何从中迁移 CodeCatalyst](migration.md)。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用合并策略生成捆绑包并指定文件
<a name="merge-strategies-lm"></a>

您可以使用合并策略生成带重新合成功能的捆绑包，并指定用于自定义蓝图的生命周期管理更新的文件。通过利用重新合成功能和合并策略，您可以管理更新并控制在部署期间更新的文件。您也可以编写自己的策略来控制如何将更改合并到现有 CodeCatalyst 项目中。

**Topics**
+ [使用重新合成功能生成文件](#three-way-merge-lm)
+ [使用合并策略](#vended-merge-strategies-lm)
+ [指定用于生命周期管理更新的文件](#specify-files-lm-updates)
+ [编写合并策略](#write-merge-strategies-lm)

## 使用重新合成功能生成文件
<a name="three-way-merge-lm"></a>

重新合成功能可以将蓝图生成的源代码与之前由同一蓝图生成的源代码合并，从而使对蓝图所做的更改能够传播到现有项目。通过 `resynth()` 函数跨蓝图输出捆绑包运行合并。重新合成功能首先会生成三个捆绑包，分别代表蓝图和项目状态的不同方面。可以使用 `yarn blueprint:resynth` 命令本地手动运行此功能，这将创建捆绑包（如果捆绑包不存在）。通过手动使用捆绑包，您可以在本地模拟和测试重新合成行为。默认情况下，蓝图仅在 `src/*` 下的存储库中运行重新合成功能，因为通常仅捆绑包的此部分受源代码控制。有关更多信息，请参阅[重新合成](custom-bp-concepts.md#resynthesis-concept)。
+ `existing-bundle` – 此捆绑包是现有项目状态的表示形式。这是由合成计算人为构造的，旨在提供蓝图上下文来说明它部署到的项目中的内容（如果有）。如果在本地运行重新合成功能时，此位置已存在某些内容，则它将被重置并视为模拟。否则，它将被设置为 `ancestor-bundle` 的内容。
+ `ancestor-bundle` – 如果蓝图输出是使用一些早期选项和/或版本合成的，则此捆绑包代表蓝图输出。如果这是此蓝图首次被添加到项目中，且其父级不存在，它将被设置为与 `existing-bundle` 相同的内容。在本地，如果该位置已存在此捆绑包，则它将被视为模拟。
+ `proposed-bundle` – 如果蓝图是使用一些新选项和/或版本合成的，则此捆绑包模拟了蓝图。这与 `synth()` 函数所生成的捆绑包相同。在本地，此捆绑包始终会被覆盖。

每个捆绑包都是在重新合成阶段创建的，可以从 `this.context.resynthesisPhase` 下的蓝图类中访问该捆绑包。
+ `resolved-bundle` – 这是最后的捆绑包，它代表已打包并部署到 CodeCatalyst 项目的内容。您可以查看已将哪些文件和差异发送到部署机制。这是解析其他三个捆绑包之间的合并的 `resynth()` 函数的输出。

通过提取 `ancestor-bundle` 和 `proposed-bundle` 之间的差异，然后将该差异添加到 `existing-bundle` 来生成 `resolved-bundle`，从而应用三向合并。所有合并策略都会将文件解析为 `resolved-bundle`。重新合成功能在 `resynth()` 期间使用蓝图的合并策略来解析这些捆绑包的覆盖范围，并根据结果生成已解析的捆绑包。

## 使用合并策略
<a name="vended-merge-strategies-lm"></a>

您可以使用蓝图库提供的合并策略。这些策略提供了解析 [使用重新合成功能生成文件](#three-way-merge-lm) 部分中提到的文件输出以及解决文件冲突的方法。
+ `alwaysUpdate` – 一种始终解析为建议的文件的策略。
+ `neverUpdate` – 一种始终解析到现有文件的策略。
+ `onlyAdd` – 一种在现有文件尚不存在时解析为建议的文件的策略。否则，解析为现有文件。
+ `threeWayMerge` – 一种在现有的、建议的和共同的父级文件之间进行三向合并的策略。如果无法干净地合并文件，则已解析的文件可能包含冲突标记。提供的文件的内容必须已通过 UTF-8 进行编码，这样策略才能生成有意义的输出。该策略尝试检测输入文件是否为二进制文件。如果该策略检测到二进制文件中存在合并冲突，则它始终返回建议的文件。
+ `preferProposed` – 一种在现有的、建议的和共同的父级文件之间进行三向合并的策略。该策略通过选择每个冲突的相关建议文件来解决冲突。
+ `preferExisting` – 一种在现有的、建议的和共同的父级文件之间进行三向合并的策略。该策略通过选择每个冲突的相关现有文件来解决冲突。

要查看合并策略的源代码，请参阅 [open-source GitHub repository](https://github.com/aws/codecatalyst-blueprints/blob/main/packages/blueprints/blueprint/src/resynthesis/merge-strategies/merge-strategies.ts#L17)。

## 指定用于生命周期管理更新的文件
<a name="specify-files-lm-updates"></a>

在重新合成期间，蓝图控制如何将更改合并到现有源存储库中。但您可能不希望将更新推送到蓝图中的每个文件。例如，像 CSS 样式表这样的示例代码是项目特定的。如果您未指定其他策略，则三向合并策略将为默认选项。蓝图可以通过指定有关存储库构造本身的合并策略来指定它们拥有哪些文件和不拥有哪些文件。蓝图可以更新其合并策略，并且可在重新合成期间使用最新策略。

```
const sourceRepo = new SourceRepository(this, {
      title: 'my-repo',
    });
    sourceRepo.setResynthStrategies([
      {
        identifier: 'dont-override-sample-code',
        description: 'This strategy is applied accross all sample code. The blueprint will create sample code, but skip attempting to update it.',
        strategy: MergeStrategies.neverUpdate,
        globs: [
          '**/src/**',
          '**/css/**',
        ],
      },
    ]);
```

可以指定多个合并策略，并且使最后一个策略优先。未发现的文件默认为类似于 Git 的三向合并。通过 `MergeStrategies` 构造提供了几种合并策略，但您可以编写自己的合并策略。提供的策略符合 [git merge strategy](https://git-scm.com/docs/merge-strategies) 驱动因素。

## 编写合并策略
<a name="write-merge-strategies-lm"></a>

除了使用提供的某个构建合并策略外，您还可以编写自己的策略。策略必须遵循标准策略接口。您必须编写一个策略函数来从 `existing-bundle`、`proposed-bundle` 和 `ancestor-bundle` 中获取文件版本，并将它们合并到单个已解析的文件中。例如：

```
type StrategyFunction = (
   /**
   * file from the ancestor bundle (if it exists)
   */
    commonAncestorFile: ContextFile | undefined, 
   /**
   * file from the existing bundle (if it exists)
   */
    existingFile: ContextFile | undefined,
   /**
   * file from the proposed bundle (if it exists)
   */ 
    proposedFile: ContextFile | undefined, 
    options?: {}) 
    /**
    * Return: file you'd like in the resolved bundle
    * passing undefined will delete the file from the resolved bundle
    */ 
=> ContextFile | undefined;
```

如果文件不存在（未定义），则该文件路径在该特定位置捆绑包中不存在。

**示例**：

```
strategies: [
          {
            identifier: 'dont-override-sample-code',
            description: 'This strategy is applied across all sample code. The blueprint will create sample code, but skip attempting to update it.',
            strategy: (ancestor, existing, proposed) => {
                const resolvedfile = ...
                ...
                // do something
                ...
                return resolvedfile
            },
            globs: [
              '**/src/**',
              '**/css/**',
            ],
          },
        ],
```