# 智能合并

> Use the UnityYAMLMerge tool to merge scene and prefab files in a semantically correct way.

使用 **UnityYAMLMerge** 工具即可以语义正确的方式合并场景和预制件文件。该工具可通过命令行访问，也可供第三方版本控制软件使用。

## 在 Unity 中设置智能合并

转到版本控制 (Version Control) 项目设置（菜单：**编辑 (Edit)** > **项目设置 (Project Settings)** > **版本控制 (Version Control)**），当您通过 **模式 (Mode)** 字段选择第三方版本控制工具时（如 Perforce 或 PlasticSCM），就将显示智能合并 ( **Smart Merge**)。智能合并菜单提供了以下选项：

* **关闭 (Off)**：仅使用偏好设置中设定的默认合并工具，不进行智能合并。
* **预合并 (Premerge)**：启用智能合并，接受纯净的合并。不纯净的合并将创建文件的预合并基础版本、他们的版本和我的版本。然后，对这些版本使用默认合并工具。
* **询问 (Ask)**：启用智能合并，但发生冲突时显示对话框让用户解决（默认设置）。

## 设置 UnityYAMLMerge 以配合第三方工具使用

Unity 编辑器随附了 UnityYAMLMerge 工具；假设 Unity 被安装在标准位置，则 UnityYAMLMerge 的路径为：

```
C:\Program Files\Unity\Editor\Data\Tools\UnityYAMLMerge.exe

or

C:\Program Files (x86)\Unity\Editor\Data\Tools\UnityYAMLMerge.exe
```

* 在 Windows 上；

```
/Applications/Unity/Unity.app/Contents/Tools/UnityYAMLMerge
```

* 在 Mac OSX 上（使用 Finder 的 *Show Package Contents* 命令访问此文件夹）。

UnityYAMLMerge 附带了一个默认的回退文件（即 mergespecfile.txt，也在 Tools 文件夹中），用于指定如何处理未解决的冲突或未知文件。它还能让您将其用作版本控制系统的主要合并工具，而这类系统（例如 git）不会根据文件扩展名自动选择合并工具。默认情况下，mergespecfile.txt 中会列出最常用的工具，但您可以编辑此文件以添加新工具或更改选项。

可通过命令行将 UnityYAMLMerge 作为独立工具运行（若要查看该工具的完整使用说明，可在运行时不带任何参数）。常见版本控制系统的设置说明如下。

### P4V

1. 转到 Preferences > Merge。
2. 选择 *Other application*。
3. 点击 *Add* 按钮。
4. 在 Extension 字段中输入 `.unity`。
5. 找到 Application 字段，输入 UnityYAMLMerge 工具的路径（见上文）。
6. 找到 Arguments 字段，输入 `merge -p %b %1 %2 %r`
7. 点击 Save。

然后按照相同的步骤添加 `.prefab` 扩展名。

### Git

将以下文本添加到 `.git` 或 `.gitconfig` 文件中：

```
	[merge]
	tool = unityyamlmerge

	[mergetool "unityyamlmerge"]
	trustExitCode = false
	cmd = '<path to UnityYAMLMerge>' merge -p "$BASE" "$REMOTE" "$LOCAL" "$MERGED"
```

### Mercurial

将以下文本添加到 `.hgrc` 文件中：

```
	[merge-patterns]
	**.unity = unityyamlmerge
	**.prefab = unityyamlmerge

	[merge-tools]
	unityyamlmerge.executable = <path to UnityYAMLMerge>
	unityyamlmerge.args = merge -p --force $base $other $local $output
	unityyamlmerge.checkprompt = True
	unityyamlmerge.premerge = False
	unityyamlmerge.binary = False
```

### SVN

将以下文本添加到 `~/.subversion/config` 文件中：

```
	[helpers]
	merge-tool-cmd = <path to UnityYAMLMerge>
```

### TortoiseGit

1. 转到 Preferences> Diff Viewer > Merge Tool，然后点击 **Advanced** 按钮。
2. 在弹出框的 Extension 字段中，输入 `.unity`。
3. 找到 **External Program** 字段，输入：

```
	<path to UnityYAMLMerge> merge -p %base %theirs %mine %merged
```

然后按照相同的步骤添加 `.prefab` 扩展名。

### PlasticSCM

1. 转到 Preferences > Merge Tools，点击 **Add** 按钮。
2. 选择 **External** 合并工具。
3. 选择 **Use with files that match the following pattern**。
4. 添加 `.unity` 扩展名。
5. 输入以下命令：

```
	<path to UnityYAMLMerge> merge -p "@basefile" "@sourcefile"  "@destinationfile" "@output"
```

然后按照相同的步骤添加 `.prefab` 扩展名。

### SourceTree

1. 转到 Tools > Options > Diff。
2. 打开 Merge Tool 下拉选单，选择 **Custom**。
3. 找到 **Merge Command** 字段，输入 UnityYAMLMerge 的路径。
4. 找到 **Arguments** 字段，输入 `merge -p $BASE $REMOTE $LOCAL $MERGED`

## 配置 mergerules.txt

要自定义 UnityYAMLMerge 合并文件的方式，请配置 mergerules.txt 文件。该文件位于 Unity 安装文件夹的 `Editor/Data/Tools` 文件夹中。各种配置选项如下。

### Arrays

数组 (Arrays) 配置分段会让 UnityYAMLMerge 将指定路径视为一个数组；或者作为带有键值的 "set"，或者作为无键值的 "plain" 数组。所有数组的默认设置是采用混合模式并尝试与一些已知的启发式方法匹配。

* \<mode> 取 "set" 或 "plain" 其中之一

#### 示例（根据默认的 mergerules 文件）

```
[arrays]
set *.GameObject.m_Component *.fileID
set *.Prefab.m_Modification.m_Modifications target.fileID target.guid propertyPath
plain *.MeshRenderer.m_Materials
plain *.Renderer.m_Materials
```

### Exclusions

排除 (Exclusions) 配置分段负责指明合并需排除的路径。如果双方都已被修改，则将双方视为冲突，并显示给用户输入。

* \<mode> 取以下项之一："include"、"exclude"、"includeIfContains"、"excludeIfContains"

#### 示例（根据默认的 mergerules 文件）

```
[exclusions]
exclude *.MeshRenderer.m_Materials.*
exclude *.SpriteRenderer.m_Materials
exclude *.SpriteRenderer.m_Color
include *.ParticleSystem.InitialModule
exclude *.ParticleSystem.*
exclude *.ParticleSystem.InitialModule.*
#excludeDepend *.MonoBehaviour m_Script ^m_
excludeIfContains *.MonoBehaviour.* x y z
excludeIfContains *.MonoBehaviour.* r g b
```

### Comparisons

比较 (Comparisons) 分段会考虑浮点值之间可以忽略的差异，以忽略逐用户的设置。启用后，在浮点比较时会考虑相对误差。您可以按照以下方式配置比较：

* "float" \<要比较的浮点值>（将 epsilon 设置为接近机器 epsilon 的默认值）
* "float" \<要比较的浮点值> \<相对比较值和绝对截止值>
* "float" \<要比较的浮点值> \<相对比较值> \<绝对截止值>

相对比较值决定了 epsilon 以及比较将如何随着浮点数相对误差的大小而调整。绝对截止值决定了在距离 0 点的哪个位置将浮点比较从绝对切换为相对（在图表上）。

**注意**：比较值应该在 float epsilon（\~0.00000011921）和 1.0 之间

#### 示例

```
[comparisons]
float *.Transform.m_LocalPosition.x 0.0000005
float *.Transform.m_LocalPosition.y 0.0000005
float *.Transform.m_LocalPosition.z 0.0000005
float *.Transform.m_LocalRotation.x 0.00005 0.001
float *.Transform.m_LocalRotation.y
float *.Transform.m_LocalRotation.z 0.00005 0.001
float *.Transform.m_LocalRotation.w
```
