# Merge

## What is the merge command

When running `chezmoi apply --interactive`, chezmoi computes the desired state (the target) from your source. If applying would change a file on disk - i.e. the destination differs from the target, usually because you edited the live file directly - a prompt appears to either overwrite, diff, skip.

Choosing merge is chezmoi's analog of resolving a git conflict by hand - except it reconciles **three** states, not two:

1. **.Destination** - the file on your system
2. **.Source** - the file in your chezmoi repo (the source of truth)
3. **.Target** - the desired state, computed by rendering the source (templates applied, etc.)

## Use a custom merge command

By default, chezmoi uses `vimdiff`. You can use a custom command by setting the
`merge.command` and `merge.args` configuration variables. The elements of
`merge.args` are interpreted as templates with the variables `.Destination`,
`.Source`, and `.Target` containing filenames of the file in the destination
state, source state, and target state respectively. For example, to use
[neovim's diff mode][nvim], specify:

=== "TOML"

```toml title="~/.config/chezmoi/chezmoi.toml"
[merge]
    command = "nvim"
    args = [
        "-d",
        "{{ .Destination }}",
        "{{ .Source }}",
        "{{ .Target }}"
    ]
```

=== "YAML"

```yaml title="~/.config/chezmoi/chezmoi.yaml"
merge:
  command: nvim
  args:
  - -d
  - "{{ .Destination }}"
  - "{{ .Source }}"
  - "{{ .Target }}"
```

=== "JSON"

```json title="~/.config/chezmoi/chezmoi.json"
{
    "merge": {
        "command": "nvim",
        "args": [
            "-d",
            "{{ .Destination }}",
            "{{ .Source }}",
            "{{ .Target }}"
        ]
    }
}
```

!!! hint

    If you generate your config file from a config file template, then you'll
    need to escape the `{{` and `}}`. That way your generated config file
    contains the `{{` and `}}` you expect.

    === "TOML"

        ```text title="~/.local/share/chezmoi/chezmoi.toml.tmpl"
        [merge]
            command = "nvim"
            args = [
                "-d",
                {{ printf "%q" "{{ .Destination }}" }},
                {{ printf "%q" "{{ .Source }}" }},
                {{ printf "%q" "{{ .Target }}" }},
            ]
        ```

    === "YAML"

        ```text title="~/.local/share/chezmoi/chezmoi.yaml.tmpl"
        merge:
          command: nvim
          args:
          - -d
          - {{ printf "%q" "{{ .Destination }}" }}
          - {{ printf "%q" "{{ .Source }}" }}
          - {{ printf "%q" "{{ .Target }}" }}
        ```

    === "JSON"

        ```text title="~/.local/share/chezmoi/chezmoi.json.tmpl"
        {
            "merge": {
                "command": "nvim",
                "args": [
                    "-d",
                    {{ printf "%q" "{{ .Destination }}" }},
                    {{ printf "%q" "{{ .Source }}" }},
                    {{ printf "%q" "{{ .Target }}" }}
                ]
            }
        }
        ```

## Use Beyond Compare as the merge tool

To use [Beyond Compare][bcomp] as the merge tool, add the following to your config:

=== "TOML"

    ```toml title="~/.config/chezmoi/chezmoi.toml"
    [merge]
        command = "bcomp"
        args = [
            "{{ .Destination }}",
            "{{ .Source }}",
            "{{ .Target }}",
            "{{ .Source }}"
        ]
    ```

=== "YAML"

    ```yaml title="~/.config/chezmoi/chezmoi.yaml"
    merge:
      command: "bcomp"
      args:
      - "{{ .Destination }}"
      - "{{ .Source }}"
      - "{{ .Target }}"
      - "{{ .Source }}"
    ```

=== "JSON"

    ```json title="~/.config/chezmoi/chezmoi.json"
    {
        "merge": {
            "command": "bcomp",
            "args": [
                "{{ .Destination }}",
                "{{ .Source }}",
                "{{ .Target }}",
                "{{ .Source }}"
            ]
        }
    }
    ```

## Use VSCode as the merge tool

To use [VSCode][vscode] as the merge tool, add the following to your config:

=== "TOML"

    ```toml title="~/.config/chezmoi/chezmoi.toml"
    [merge]
    command = "bash"
    args = [
        "-c",
        "cp {{ .Target | quote }} {{ printf \"%s.base\" .Target | quote }} && code --new-window --wait --merge {{ .Destination | quote }} {{ .Target | quote }} {{ printf \"%s.base\" .Target | quote }} {{ .Source | quote }}",
    ]
    ```

=== "YAML"

    ```yaml title="~/.config/chezmoi/chezmoi.yaml"
    merge:
      command: "bash"
      args:
      - "-c"
      - "cp {{ .Target | quote }} {{ printf \"%s.base\" .Target | quote }} && code --new-window --wait --merge {{ .Destination | quote }} {{ .Target | quote }} {{ printf \"%s.base\" .Target | quote }} {{ .Source | quote }}"
    ```

=== "JSON"

    ```json title="~/.config/chezmoi.chezmoi.json"
    {
        "merge": {
            "command": "bash",
            "args": [
                "-c",
                "cp {{ .Target | quote }} {{ printf \"%s.base\" .Target | quote }} && code --new-window --wait --merge {{ .Destination | quote }} {{ .Target | quote }} {{ printf \"%s.base\" .Target | quote }} {{ .Source | quote }}",
            ]
        }
    }
    ```

[bcomp]: https://www.scootersoftware.com/
[nvim]: https://neovim.io/doc/user/diff.html
[vscode]: https://code.visualstudio.com/
