> ## Documentation Index
> Fetch the complete documentation index at: https://docs.diversion.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# External Merge Tools

> Resolve merge conflicts with your own merge tools, such as UnityYAMLMerge, KDiff3, or Meld.

When a merge has conflicts, Diversion can run a merge tool that you choose on each conflicting file. The tool merges the two versions of the file, and Diversion saves the result to the merge.

Use this for files that need a special merge tool, for example:

* Unity scenes and prefabs, with UnityYAMLMerge (Unity Smart Merge)
* JSON, YAML, or source code, with a syntax-aware tool such as mergiraf
* Any file that you want to merge by hand in a visual tool, such as KDiff3 or Meld

## Quick start

1. Add a merge tool, once per computer. This one merges JSON files:
   ```bash theme={null}
   dv merge-tool add --name mergiraf --pattern '\.json$' --cmd 'mergiraf merge $ANCESTOR $CURRENT $INCOMING -o $RESULT'
   ```
2. Merge with your tools:
   ```bash theme={null}
   dv merge <branch> --conflict_resolution merge-tool
   ```
3. Diversion merges what it can on the server. For each conflict that is left, it runs the tool that matches the file. If a conflict is still open at the end, finish it in the Diversion app.

For Unity and other tools, see [Examples](#examples).

## How it works

1. You start a merge, update, or revert with the `merge-tool` conflict resolution.
2. Diversion first merges what it can on the server. If the two sides changed different parts of a text file, Diversion merges it for you, and no tool runs.
3. For each conflict that is left, Diversion finds the first tool whose pattern matches the file path. It downloads the versions of the file to temporary files and runs the tool.
4. If the tools resolve every conflict, Diversion completes the merge and creates the commit.
5. If some conflicts are not resolved, the merge stays open. You resolve the rest in the Diversion app. The conflicts that the tools resolved stay resolved.

<Note>
  Merge tools run on your computer. Your tool settings are saved for your user on this computer, not in the repository, so each team member sets up their own tools.
</Note>

## Set up a merge tool

<Steps>
  <Step title="Install the tool">
    Install the merge tool and find the full path to its program. If the program is on your `PATH`, the program name is enough.
  </Step>

  <Step title="Add the tool to Diversion">
    Tell Diversion which files the tool handles and how to run it:

    ```bash theme={null}
    dv merge-tool add --name <name> --pattern '<regex>' --cmd '<command>'
    ```

    See [Examples](#examples) for ready-to-use commands.
  </Step>

  <Step title="Check your setup">
    List your tools, in the order Diversion matches them:

    ```bash theme={null}
    dv merge-tool
    ```
  </Step>
</Steps>

### Command placeholders

In `--cmd`, use these placeholders for the file paths. Diversion replaces them with temporary files before it runs the tool.

| Placeholder | Replaced with                                                                                                                      |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `$ANCESTOR` | The common ancestor: the file before either side changed it                                                                        |
| `$CURRENT`  | Your side: the branch you merge into, or your workspace for `update` and `revert`                                                  |
| `$INCOMING` | The incoming side: the branch or commit you merge in, the latest branch version for `update`, or the reverted content for `revert` |
| `$RESULT`   | The output file. The tool must write the merged result here. It starts empty.                                                      |

Rules for the command:

* `--cmd` must include `$RESULT`.
* The command runs directly, not through a shell. Pipes (`|`), redirects (`>`), and environment variables do not work. If you need them, put the steps in a script, and set the script as the command.
* Put double quotes around a program path that has spaces.
* On Mac and Linux, put the whole `--cmd` value in single quotes. Otherwise your shell replaces `$ANCESTOR` and the other placeholders before Diversion sees them.

The temporary files keep the original file extension, for example `local.prefab`. This matters for tools that choose how to merge from the extension, such as UnityYAMLMerge and mergiraf.

### File patterns

`--pattern` is a regular expression. Diversion matches it against the file path in the repository.

| Pattern                  | Matches                                        |
| ------------------------ | ---------------------------------------------- |
| `\.prefab$`              | Files that end with `.prefab`                  |
| `\.(unity\|prefab)$`     | Files that end with `.unity` or `.prefab`      |
| `Characters/.*\.prefab$` | `.prefab` files inside any `Characters` folder |
| `.*`                     | Every file                                     |

If more than one tool matches a file, **the first tool in the list wins**. `dv merge-tool add` puts a new tool at the end of the list. Use `dv merge-tool` to see the order.

A file that matches no tool is left for you to resolve in the Diversion app.

### Exit codes and visual tools

By default, the exit code of the tool decides the result, the same way as `git mergetool`:

| Exit code       | Result                                                                      |
| --------------- | --------------------------------------------------------------------------- |
| `0`             | Resolved. Diversion saves the content of `$RESULT`.                         |
| `1` to `127`    | The tool left the conflict unresolved. You resolve it in the Diversion app. |
| `128` or higher | The tool failed.                                                            |

Some visual tools exit with `0` even when you close them without saving. For these tools, add `--no-trust-exit-code`. Diversion then ignores the exit code and checks `$RESULT`:

* If the tool wrote `$RESULT` and the file has no conflict markers (`<<<<<<<`), the conflict is resolved.
* Otherwise, Diversion asks: `Was the merge successful? [y/n]`.
* If there is no terminal to ask in, for example in a CI job, the conflict stays unresolved.

## Examples

### Unity Smart Merge (UnityYAMLMerge)

UnityYAMLMerge comes with the Unity Editor. It merges Unity scenes, prefabs, and other YAML assets. It works only on assets saved as text, so set **Asset Serialization Mode** to `Force Text` first (see [Unity best practices](/unity/unity-best-practices#initial-setup)).

Change `6000.0.23f1` to your Unity version:

<CodeGroup>
  ```bash macOS theme={null}
  dv merge-tool add --name unity-yaml \
    --pattern '\.(unity|prefab|asset|mat|anim|controller)$' \
    --cmd '"/Applications/Unity/Hub/Editor/6000.0.23f1/Unity.app/Contents/Tools/UnityYAMLMerge" merge -p $ANCESTOR $INCOMING $CURRENT $RESULT'
  ```

  ```bat Windows (Command Prompt) theme={null}
  dv merge-tool add --name unity-yaml --pattern "\.(unity|prefab|asset|mat|anim|controller)$" --cmd "\"C:\Program Files\Unity\Hub\Editor\6000.0.23f1\Editor\Data\Tools\UnityYAMLMerge.exe\" merge -p $ANCESTOR $INCOMING $CURRENT $RESULT"
  ```
</CodeGroup>

<Note>
  UnityYAMLMerge takes the files in the order base, remote, local, merged. This is different from most other tools.
</Note>

<Tip>
  On Windows, run the example in Command Prompt. PowerShell passes quotes inside arguments differently in different versions, so the quoted program path can break.
</Tip>

### mergiraf (JSON, YAML, and code)

[mergiraf](https://mergiraf.org) understands the syntax of many file types. It can merge two changes on the same line, such as two new keys in one JSON object.

```bash theme={null}
dv merge-tool add --name mergiraf \
  --pattern '\.(json|ya?ml|toml)$' \
  --cmd 'mergiraf merge $ANCESTOR $CURRENT $INCOMING -o $RESULT'
```

### KDiff3

KDiff3 merges what it can on its own. It opens a window only when a conflict is left for you.

```bash theme={null}
dv merge-tool add --name kdiff3 \
  --pattern '\.(ini|cfg)$' \
  --cmd 'kdiff3 $ANCESTOR $CURRENT $INCOMING -o $RESULT --auto'
```

### Meld

Meld exits with `0` even when you close it without saving, so add `--no-trust-exit-code`:

```bash theme={null}
dv merge-tool add --name meld \
  --pattern '\.txt$' \
  --cmd 'meld $CURRENT $ANCESTOR $INCOMING -o $RESULT' \
  --no-trust-exit-code
```

## Resolve conflicts with your merge tools

### From the CLI

Add `--conflict_resolution merge-tool` to [`dv merge`](/cmd-ref/merge), [`dv update`](/cmd-ref/update), or [`dv revert`](/cmd-ref/revert):

```bash theme={null}
dv merge feature/new-level --conflict_resolution merge-tool
dv update --conflict_resolution merge-tool
dv revert <commit_id> --conflict_resolution merge-tool
```

If you have no tools set up, the command stops before it starts the merge.

The tools run one conflict at a time. The CLI then prints the result for each file:

```text theme={null}
merge encountered conflicts, resolving with external merge tools
Resolved 1 conflict(s) with external tools:
  - Assets/Prefabs/Player.prefab (unity-yaml)
Skipped 1 conflict(s), left for manual resolution:
  - Assets/Textures/Hero.psd: no merge tool is configured for this file
Not all conflicts were resolved. Please resolve the rest manually:
https://app.diversion.dev/repo/<repo_id>/merges/<merge_id>
```

| Result       | Meaning                                                                                           | What to do                                                                       |
| ------------ | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| **Resolved** | The tool merged the file. Diversion saved the result to the merge.                                | Nothing.                                                                         |
| **Skipped**  | No tool matches the file, the tool left the conflict unresolved, or you answered `n`.             | Open the printed link and resolve the file in the Diversion app.                 |
| **Failed**   | The tool did not start, it exited with code `128` or higher, or a file download or upload failed. | Check the tool with `dv merge-tool`, then resolve the file in the Diversion app. |

Diversion completes the merge only when every conflict is resolved. If any conflict is skipped or failed, the merge stays open and the command exits with a non-zero exit code, so scripts can detect it.

## Manage your merge tools

```bash theme={null}
dv merge-tool            # list your tools, in match order
dv merge-tool add ...    # add a tool, or update the tool with this name
dv merge-tool -d <name>  # remove a tool
```

When you add a tool with a name that already exists, Diversion replaces it and keeps its place in the list.

Diversion saves your tools in `~/.diversion/merge_tools.json` (on Windows, `%USERPROFILE%\.diversion\merge_tools.json`). Use `dv merge-tool` to change them instead of editing the file.

See [`dv merge-tool`](/cmd-ref/merge-tool) for all options.

## Troubleshooting

| Message                                                                   | Cause and fix                                                                                                                               |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `no merge tools configured`                                               | You have no tools. Add one with `dv merge-tool add`.                                                                                        |
| `no merge tool is configured for this file`                               | No pattern matches the file path. Check your patterns with `dv merge-tool`.                                                                 |
| `the tool exited with code N and left the conflict unresolved`            | The tool could not merge the file on its own. Resolve it in the Diversion app.                                                              |
| `the tool wrote an empty file while a side still had content`             | The tool did not write its result to `$RESULT`. Check that the command writes to `$RESULT`, for example with `-o $RESULT`.                  |
| `the two sides differ only in metadata`                                   | The file content is the same, but something else changed, such as the file name. A merge tool cannot help. Resolve it in the Diversion app. |
| `failed to run merge tool`                                                | Diversion could not start the program. Use the full path to the program, in double quotes if it has spaces.                                 |
| A visual tool marks the file as resolved when you close it without saving | Add the tool again with `--no-trust-exit-code`.                                                                                             |

## Related

* [`dv merge-tool`](/cmd-ref/merge-tool) -- CLI reference for managing merge tools
* [Conflicts](/concepts/conflicts) -- types of conflicts and how to resolve them
* [Branching and merging](/core-concepts/branching-merging)
* [Unity best practices](/unity/unity-best-practices)
