# `TerminusDB.Branch`
[🔗](https://github.com/thanos/terminusdb-client-elixir/blob/v0.3.3/lib/terminus_db/branch.ex#L1)

Branch management API for TerminusDB.

Wraps the `/api/branch/{path}` endpoints. Branches are git-like pointers to
commits within a repository. Creating a branch forks from an existing branch
(default: `main`).

All functions require a `TerminusDB.Config` scoped to a database (via
`TerminusDB.Config.with_database/2`). The organization defaults to
`config.organization` and the repository to `config.repo` (default `local`),
both overridable per call.

## Quick start

    config =
      TerminusDB.Config.new(endpoint: "http://localhost:6363")
      |> TerminusDB.Config.with_database("mydb")

    # Create a branch (forks from main by default)
    {:ok, _} = TerminusDB.Branch.create(config, "feature")

    # Check it exists
    true = TerminusDB.Branch.exists?(config, "feature")

    # Delete it
    {:ok, _} = TerminusDB.Branch.delete(config, "feature")

# `branch_opt`

```elixir
@type branch_opt() ::
  {:organization, String.t()}
  | {:repo, String.t()}
  | {:from, String.t()}
  | {:author, String.t()}
  | {:message, String.t()}
```

# `create`

```elixir
@spec create(TerminusDB.Config.t(), String.t(), [branch_opt()]) ::
  {:ok, map()} | {:error, TerminusDB.Error.t()}
```

Creates a new branch `branch_name` in the configured (or given) repository.

The branch is forked from the branch named in `:from` (default: `config.branch`,
which defaults to `"main"`).

## Options

- `:from` — the branch to fork from (default: `config.branch`).
- `:organization` — overrides `config.organization`.
- `:repo` — overrides `config.repo` (`local` or a remote name).

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> {:ok, resp} = TerminusDB.Branch.create(config, "feature")
    iex> resp["api:status"]
    "api:success"

Fork from a specific branch:

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> {:ok, resp} = TerminusDB.Branch.create(config, "dev", from: "main")
    iex> resp["api:status"]
    "api:success"

# `create!`

```elixir
@spec create!(TerminusDB.Config.t(), String.t(), [branch_opt()]) :: map()
```

Creates a branch, returning the response body or raising `TerminusDB.Error`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> TerminusDB.Branch.create!(config, "feature")
    %{"api:status" => "api:success"}

# `delete`

```elixir
@spec delete(TerminusDB.Config.t(), String.t(), [branch_opt()]) ::
  {:ok, map() | nil} | {:error, TerminusDB.Error.t()}
```

Deletes the branch `branch_name`.

## Options

- `:organization` — overrides `config.organization`.
- `:repo` — overrides `config.repo`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> {:ok, resp} = TerminusDB.Branch.delete(config, "feature")
    iex> resp["api:status"]
    "api:success"

# `delete!`

```elixir
@spec delete!(TerminusDB.Config.t(), String.t(), [branch_opt()]) :: map() | nil
```

Deletes a branch, returning the response body or raising `TerminusDB.Error`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> TerminusDB.Branch.delete!(config, "feature")
    %{"api:status" => "api:success"}

# `exists?`

```elixir
@spec exists?(TerminusDB.Config.t(), String.t(), [branch_opt()]) :: boolean()
```

Returns `true` if the branch `branch_name` exists, `false` otherwise.

Checks the database's branch list via `GET /api/db/:org/:db?branches=true`.
A 404 on the database means it does not exist (so the branch cannot either);
any other non-success response raises `TerminusDB.Error`.

## Options

- `:organization` — overrides `config.organization`.
- `:repo` — overrides `config.repo`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req ->
    ...>     {req, Req.Response.new(status: 200, body: %{"branches" => ["main", "feature"], "path" => "admin/mydb"})}
    ...>   end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> TerminusDB.Branch.exists?(config, "main")
    true

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req ->
    ...>     {req, Req.Response.new(status: 200, body: %{"branches" => ["main"], "path" => "admin/mydb"})}
    ...>   end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> TerminusDB.Branch.exists?(config, "missing")
    false

# `reset`

```elixir
@spec reset(TerminusDB.Config.t(), String.t(), [branch_opt()]) ::
  {:ok, map()} | {:error, TerminusDB.Error.t()}
```

Hard-resets the branch HEAD to a specific commit.

## Options

- `:organization` — overrides `config.organization`.
- `:repo` — overrides `config.repo`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> {:ok, resp} = TerminusDB.Branch.reset(config, "admin/mydb/local/commit/abc123")
    iex> resp["api:status"]
    "api:success"

# `reset!`

```elixir
@spec reset!(TerminusDB.Config.t(), String.t(), [branch_opt()]) :: map()
```

Hard-resets the branch HEAD, or raises.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> TerminusDB.Branch.reset!(config, "admin/mydb/local/commit/abc")
    %{"api:status" => "api:success"}

# `squash`

```elixir
@spec squash(TerminusDB.Config.t(), [branch_opt()]) ::
  {:ok, map()} | {:error, TerminusDB.Error.t()}
```

Squashes the current branch HEAD into a single commit.

## Options

- `:author` — commit author.
- `:message` — commit message.
- `:organization` — overrides `config.organization`.
- `:repo` — overrides `config.repo`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success", "api:commit" => "abc123"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> {:ok, resp} = TerminusDB.Branch.squash(config, author: "admin", message: "squash")
    iex> resp["api:commit"]
    "abc123"

# `squash!`

```elixir
@spec squash!(TerminusDB.Config.t(), [branch_opt()]) :: map()
```

Squashes the branch HEAD, or raises.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success", "api:commit" => "abc"})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> TerminusDB.Branch.squash!(config, author: "admin", message: "squash")
    %{"api:commit" => "abc"}

---

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