# `Git.Conflicts`
[🔗](https://github.com/joshrotenberg/git_wrapper_ex/blob/main/lib/git/conflicts.ex#L1)

Merge conflict detection and resolution helpers that compose `Git.status/1`
and `Git.merge/2`.

All functions accept an optional keyword list. Use `:config` to specify the
repository via a `Git.Config` struct; when omitted a default config is built
from the environment.

# `abort`

```elixir
@spec abort(keyword()) :: {:ok, :done} | {:error, term()}
```

Aborts whichever git operation is currently in progress.

Generalizes `abort_merge/1` to any conflicted operation. Probes the
repository's git directory to detect an in-progress merge (`MERGE_HEAD`),
rebase (a `rebase-merge` or `rebase-apply` directory), cherry-pick
(`CHERRY_PICK_HEAD`), or revert (`REVERT_HEAD`), then dispatches the matching
abort: `Git.merge(:abort)`, `Git.rebase(abort: true)`,
`Git.cherry_pick(abort: true)`, or `Git.revert(abort: true)`.

Returns `{:ok, :done}` on success, or `{:error, :no_operation_in_progress}`
when nothing is in progress.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, :done} = Git.Conflicts.abort()

# `abort_merge`

```elixir
@spec abort_merge(keyword()) :: {:ok, :done} | {:error, term()}
```

Aborts an in-progress conflicted merge.

Delegates to `Git.merge(:abort)`.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, :done} = Git.Conflicts.abort_merge()

# `base`

```elixir
@spec base(
  String.t(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}
```

Returns the base (merge stage 1) content of a conflicted path.

Reads the common-ancestor version via `git show :1:<path>`. Returns
`{:ok, content}` with the raw file content, or `{:error, _}` when stage 1
does not exist (for example an add/add conflict has no common ancestor).

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, content} = Git.Conflicts.base("shared.txt")

# `continue`

```elixir
@spec continue(keyword()) :: {:ok, :done | Git.CommitResult.t()} | {:error, term()}
```

Continues whichever git operation is currently in progress.

Uses the same detection as `abort/1`. For a rebase, cherry-pick, or revert it
advances the sequencer with `Git.rebase(continue_rebase: true)`,
`Git.cherry_pick(continue_pick: true)`, or `Git.revert(continue_revert: true)`,
forcing a no-op editor so the prepared commit message is reused without a TTY.
For a merge it concludes with `Git.commit(nil, no_edit: true)` rather than
`git merge --continue`, which opens an editor and fails without a TTY.

Callers must stage their conflict resolutions (for example with `resolve/2`)
before calling. Returns `{:ok, :done}` for rebase/cherry-pick/revert,
`{:ok, %Git.CommitResult{}}` for a concluded merge, or
`{:error, :no_operation_in_progress}` when nothing is in progress.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, _result} = Git.Conflicts.continue()

# `detect`

```elixir
@spec detect(keyword()) :: {:ok, boolean()} | {:error, term()}
```

Checks whether the repository is in a conflicted state.

Uses `Git.status/1` and inspects entries for unmerged status codes.

Returns `{:ok, true}` when conflicts exist, `{:ok, false}` otherwise.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, false} = Git.Conflicts.detect()

# `files`

```elixir
@spec files(keyword()) :: {:ok, [String.t()]} | {:error, term()}
```

Lists file paths that have merge conflicts.

Uses `Git.status/1` and filters for entries with unmerged status codes.

Returns `{:ok, [String.t()]}`.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, files} = Git.Conflicts.files()

# `ours`

```elixir
@spec ours(
  String.t(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}
```

Returns our (merge stage 2) content of a conflicted path.

Reads our side via `git show :2:<path>`. Returns `{:ok, content}` with the
raw file content, or `{:error, _}` when stage 2 does not exist.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, content} = Git.Conflicts.ours("shared.txt")

# `resolve`

```elixir
@spec resolve(
  String.t() | [String.t()],
  keyword()
) :: {:ok, :done} | {:error, term()}
```

Resolves conflicts by choosing one side, selected by the `:using` option.

A convenience dispatcher over `take_ours/2` and `take_theirs/2`:
`using: :ours` delegates to `take_ours/2` and `using: :theirs` delegates to
`take_theirs/2`. Any other value, including a missing `:using`, returns
`{:error, {:invalid_strategy, value}}`. Accepts a single path or a list of
paths.

Returns `{:ok, :done}` on success.

## Options

  * `:using` - `:ours` or `:theirs` (required)
  * `:config` - a `Git.Config` struct

## Examples

    {:ok, :done} = Git.Conflicts.resolve("shared.txt", using: :ours)
    {:ok, :done} = Git.Conflicts.resolve(["a.txt", "b.txt"], using: :theirs)

# `resolved?`

```elixir
@spec resolved?(keyword()) :: {:ok, boolean()} | {:error, term()}
```

Checks whether all conflicts have been resolved.

This is the inverse of `detect/1` -- returns `{:ok, true}` when no unmerged
files exist.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, true} = Git.Conflicts.resolved?()

# `take_ours`

```elixir
@spec take_ours(
  String.t() | [String.t()],
  keyword()
) :: {:ok, :done} | {:error, term()}
```

Resolves conflicts by choosing our side, then stages the result.

Delegates to `Git.restore(files: ..., ours: true)` to write our version into
the working tree, then `Git.add/1` to collapse the merge stages and mark the
path resolved. Accepts a single path or a list of paths.

Returns `{:ok, :done}` on success.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, :done} = Git.Conflicts.take_ours("shared.txt")
    {:ok, :done} = Git.Conflicts.take_ours(["a.txt", "b.txt"])

# `take_theirs`

```elixir
@spec take_theirs(
  String.t() | [String.t()],
  keyword()
) :: {:ok, :done} | {:error, term()}
```

Resolves conflicts by choosing their side, then stages the result.

Delegates to `Git.restore(files: ..., theirs: true)` to write their version
into the working tree, then `Git.add/1` to collapse the merge stages and mark
the path resolved. Accepts a single path or a list of paths.

Returns `{:ok, :done}` on success.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, :done} = Git.Conflicts.take_theirs("shared.txt")
    {:ok, :done} = Git.Conflicts.take_theirs(["a.txt", "b.txt"])

# `theirs`

```elixir
@spec theirs(
  String.t(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}
```

Returns their (merge stage 3) content of a conflicted path.

Reads the other side via `git show :3:<path>`. Returns `{:ok, content}` with
the raw file content, or `{:error, _}` when stage 3 does not exist.

## Options

  * `:config` - a `Git.Config` struct

## Examples

    {:ok, content} = Git.Conflicts.theirs("shared.txt")

---

*Consult [api-reference.md](api-reference.md) for complete listing*
