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

A stateful repository abstraction for the git CLI wrapper.

`Git.Repo` holds a `Git.Config` struct and the resolved repository path,
providing a cleaner API for working with a specific repository. Instead of
passing `config: config` to every `Git` function, you create a `Repo` and
call functions on it.

## Opening an existing repository

    {:ok, repo} = Git.Repo.open("/path/to/repo")
    {:ok, status} = Git.Repo.status(repo)
    {:ok, commits} = Git.Repo.log(repo, max_count: 5)

## Initializing a new repository

    {:ok, repo} = Git.Repo.init("/tmp/new-repo")

## Cloning a repository

    {:ok, repo} = Git.Repo.clone("https://github.com/owner/repo.git", "/tmp/clone")

## Pipeline pattern

    Git.Repo.open("/path/to/repo")
    |> Git.Repo.run(fn repo ->
      Git.Repo.add(repo, all: true)
      Git.Repo.commit(repo, "feat: new feature")
      {:ok, repo}
    end)

# `t`

```elixir
@type t() :: %Git.Repo{config: Git.Config.t(), path: String.t()}
```

# `add`

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

Runs `git add` on the repository.

See `Git.add/1` for available options.

# `am`

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

Runs `git am` on the repository.

See `Git.am/1` for available options.

# `apply_patch`

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

Runs `git apply` on the repository.

See `Git.apply_patch/1` for available options.

# `archive`

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

Runs `git archive` on the repository.

See `Git.archive/1` for available options.

# `bisect`

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

Runs `git bisect` on the repository.

See `Git.bisect/1` for available options.

# `blame`

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

Runs `git blame` on the repository.

See `Git.blame/2` for available options.

# `branch`

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

Runs `git branch` on the repository.

See `Git.branch/1` for available options.

# `bundle`

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

Runs `git bundle` on the repository.

See `Git.bundle/1` for available options.

# `cat_file`

```elixir
@spec cat_file(t(), String.t(), keyword()) ::
  {:ok, atom()}
  | {:ok, integer()}
  | {:ok, String.t()}
  | {:ok, boolean()}
  | {:error, term()}
```

Runs `git cat-file` on the repository.

See `Git.cat_file/2` for available options.

# `check_ignore`

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

Runs `git check-ignore` on the repository.

See `Git.check_ignore/1` for available options.

# `checkout`

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

Runs `git checkout` on the repository.

See `Git.checkout/1` for available options.

# `cherry`

```elixir
@spec cherry(
  t(),
  keyword()
) :: {:ok, [Git.CherryEntry.t()]} | {:error, term()}
```

Runs `git cherry` on the repository.

See `Git.cherry/1` for available options.

# `cherry_pick`

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

Runs `git cherry-pick` on the repository.

See `Git.cherry_pick/1` for available options.

# `clean`

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

Runs `git clean` on the repository.

See `Git.clean/1` for available options.

# `clone`

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

Clones a repository from `url` into `path`.

Runs `git clone` and returns a `Git.Repo` pointing at the cloned directory.

## Options

  * `:depth` - create a shallow clone with the given number of commits
  * `:branch` - check out the given branch after cloning
  * `:directory` - name of the target directory (default: inferred from URL)

## Examples

    {:ok, repo} = Git.Repo.clone("https://github.com/owner/repo.git", "/tmp/clone")
    {:ok, repo} = Git.Repo.clone("https://github.com/owner/repo.git", "/tmp/clone", depth: 1)

# `commit`

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

Runs `git commit` on the repository.

See `Git.commit/2` for available options.

# `describe`

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

Runs `git describe` on the repository.

See `Git.describe/1` for available options.

# `diff`

```elixir
@spec diff(
  t(),
  keyword()
) :: {:ok, Git.Diff.t()} | {:error, term()}
```

Runs `git diff` on the repository.

See `Git.diff/1` for available options.

# `fetch`

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

Runs `git fetch` on the repository.

See `Git.fetch/1` for available options.

# `for_each_ref`

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

Runs `git for-each-ref` on the repository.

See `Git.for_each_ref/1` for available options.

# `format_patch`

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

Runs `git format-patch` on the repository.

See `Git.format_patch/1` for available options.

# `fsck`

```elixir
@spec fsck(
  t(),
  keyword()
) :: {:ok, [map()]} | {:error, term()}
```

Runs `git fsck` on the repository.

See `Git.fsck/1` for available options.

# `gc`

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

Runs `git gc` on the repository.

See `Git.gc/1` for available options.

# `git_config`

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

Runs `git config` on the repository.

See `Git.git_config/1` for available options.

# `grep`

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

Runs `git grep` on the repository.

See `Git.grep/2` for available options.

# `hash_object`

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

Runs `git hash-object` on the repository.

See `Git.hash_object/1` for available options.

# `init`

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

Initializes a new git repository at `path`.

Creates the directory if it does not exist, runs `git init`, and returns
a `Git.Repo` pointing at the new repository.

## Options

  * `:bare` - when `true`, initializes a bare repository (default `false`)

## Examples

    {:ok, repo} = Git.Repo.init("/tmp/new-repo")
    {:ok, repo} = Git.Repo.init("/tmp/bare-repo", bare: true)

# `interpret_trailers`

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

Runs `git interpret-trailers` on the repository.

See `Git.interpret_trailers/1` for available options.

# `log`

```elixir
@spec log(
  t(),
  keyword()
) :: {:ok, [Git.Commit.t()]} | {:error, term()}
```

Runs `git log` on the repository.

See `Git.log/1` for available options.

# `ls_files`

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

Runs `git ls-files` on the repository.

See `Git.ls_files/1` for available options.

# `ls_remote`

```elixir
@spec ls_remote(
  t(),
  keyword()
) :: {:ok, [Git.LsRemoteEntry.t()]} | {:error, term()}
```

Runs `git ls-remote` on the repository.

See `Git.ls_remote/1` for available options.

# `ls_tree`

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

Runs `git ls-tree` on the repository.

See `Git.ls_tree/1` for available options.

# `maintenance`

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

Runs `git maintenance` on the repository.

See `Git.maintenance/1` for available options.

# `merge`

```elixir
@spec merge(t(), String.t() | :abort, keyword()) ::
  {:ok, Git.MergeResult.t()} | {:ok, :done} | {:error, term()}
```

Runs `git merge` on the repository.

See `Git.merge/2` for available options.

# `merge_base`

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

Runs `git merge-base` on the repository.

See `Git.merge_base/1` for available options.

# `mv`

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

Runs `git mv` on the repository.

See `Git.mv/3` for available options.

# `notes`

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

Runs `git notes` on the repository.

See `Git.notes/1` for available options.

# `ok`

```elixir
@spec ok(t()) :: {:ok, t()}
```

Wraps a repo in an ok tuple for use as the start of a pipeline.

## Examples

    Git.Repo.ok(repo)
    |> Git.Repo.run(fn repo -> ... end)

# `open`

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

Opens an existing git repository at `path`.

Validates that the path exists and is a git repository by calling
`git rev-parse --show-toplevel`. The resolved toplevel path is stored in
both the struct and the config's `working_dir`.

Returns `{:ok, %Git.Repo{}}` on success or `{:error, reason}` on failure.

## Examples

    {:ok, repo} = Git.Repo.open("/path/to/repo")
    repo.path  #=> "/path/to/repo"

# `open!`

```elixir
@spec open!(String.t()) :: t()
```

Opens an existing git repository at `path`, raising on error.

Same as `open/1` but raises on failure.

## Examples

    repo = Git.Repo.open!("/path/to/repo")

# `pull`

```elixir
@spec pull(
  t(),
  keyword()
) :: {:ok, Git.PullResult.t()} | {:error, term()}
```

Runs `git pull` on the repository.

See `Git.pull/1` for available options.

# `push`

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

Runs `git push` on the repository.

See `Git.push/1` for available options.

# `range_diff`

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

Runs `git range-diff` on the repository.

See `Git.range_diff/1` for available options.

# `rebase`

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

Runs `git rebase` on the repository.

See `Git.rebase/1` for available options.

# `reflog`

```elixir
@spec reflog(
  t(),
  keyword()
) :: {:ok, [Git.ReflogEntry.t()]} | {:error, term()}
```

Runs `git reflog` on the repository.

See `Git.reflog/1` for available options.

# `remote`

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

Runs `git remote` on the repository.

See `Git.remote/1` for available options.

# `rerere`

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

Runs `git rerere` on the repository.

See `Git.rerere/1` for available options.

# `reset`

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

Runs `git reset` on the repository.

See `Git.reset/1` for available options.

# `restore`

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

Runs `git restore` on the repository.

See `Git.restore/1` for available options.

# `rev_list`

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

Runs `git rev-list` on the repository.

See `Git.rev_list/1` for available options.

# `rev_parse`

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

Runs `git rev-parse` on the repository.

See `Git.rev_parse/1` for available options.

# `revert`

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

Runs `git revert` on the repository.

See `Git.revert/1` for available options.

# `rm`

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

Runs `git rm` on the repository.

See `Git.rm/1` for available options.

# `run`

```elixir
@spec run({:ok, t()} | {:error, term()}, (t() -&gt; {:ok, t()} | {:error, term()})) ::
  {:ok, t()} | {:error, term()}
```

Runs a function in a pipeline, halting on error.

If given `{:ok, repo}`, calls `fun.(repo)`. If given `{:error, _}`,
passes the error through unchanged.

## Examples

    Git.Repo.open("/path/to/repo")
    |> Git.Repo.run(fn repo ->
      Git.Repo.add(repo, all: true)
      {:ok, repo}
    end)

# `shortlog`

```elixir
@spec shortlog(
  t(),
  keyword()
) :: {:ok, [Git.ShortlogEntry.t()]} | {:error, term()}
```

Runs `git shortlog` on the repository.

See `Git.shortlog/1` for available options.

# `show`

```elixir
@spec show(
  t(),
  keyword()
) :: {:ok, Git.ShowResult.t()} | {:error, term()}
```

Runs `git show` on the repository.

See `Git.show/1` for available options.

# `show_ref`

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

Runs `git show-ref` on the repository.

See `Git.show_ref/1` for available options.

# `sparse_checkout`

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

Runs `git sparse-checkout` on the repository.

See `Git.sparse_checkout/1` for available options.

# `stash`

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

Runs `git stash` on the repository.

See `Git.stash/1` for available options.

# `status`

```elixir
@spec status(
  t(),
  keyword()
) :: {:ok, Git.Status.t()} | {:error, term()}
```

Runs `git status` on the repository.

See `Git.status/1` for available options.

# `submodule`

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

Runs `git submodule` on the repository.

See `Git.submodule/1` for available options.

# `switch`

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

Runs `git switch` on the repository.

See `Git.switch/1` for available options.

# `symbolic_ref`

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

Runs `git symbolic-ref` on the repository.

See `Git.symbolic_ref/1` for available options.

# `tag`

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

Runs `git tag` on the repository.

See `Git.tag/1` for available options.

# `update_ref`

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

Runs `git update-ref` on the repository.

See `Git.update_ref/1` for available options.

# `verify_commit`

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

Runs `git verify-commit` on the repository.

See `Git.verify_commit/2` for available options.

# `verify_tag`

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

Runs `git verify-tag` on the repository.

See `Git.verify_tag/2` for available options.

# `worktree`

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

Runs `git worktree` on the repository.

See `Git.worktree/1` for available options.

---

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