An Elixir wrapper for the git CLI.

Provides functions for common git operations by shelling out to the git binary. Each function accepts an options keyword list that can include a :config key with a Git.Config struct to customize behavior.

All functions return {:ok, result} on success or {:error, reason} on failure. A non-zero exit code from git produces {:error, {stdout, exit_code}}.

Configuration

Pass a Git.Config struct via the :config option to control the git binary, working directory, environment variables, and command timeout:

config = Git.Config.new(
  working_dir: "/path/to/repo",
  timeout: 60_000
)

Git.status(config: config)

When :config is omitted, a default config is built from the environment: the git binary is located via GIT_PATH or System.find_executable("git"), the working directory defaults to the current directory, and the timeout is 30 seconds.

Examples

Repository status

{:ok, status} = Git.status()
status.branch   #=> "main"
status.ahead    #=> 0
status.entries  #=> [%{index: "M", working_tree: " ", path: "lib/foo.ex"}]

Commit history

{:ok, commits} = Git.log(max_count: 5)
hd(commits).subject  #=> "feat: add new feature"
hd(commits).hash     #=> "e3a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9"

Staging and committing

{:ok, :done}   = Git.add(all: true)
{:ok, result}  = Git.commit("feat: ship it")
result.hash    #=> "abc1234"
result.subject #=> "feat: ship it"

Branches

{:ok, branches} = Git.branch()
Enum.find(branches, & &1.current).name  #=> "main"

{:ok, :done}     = Git.branch(create: "feat/new-thing")
{:ok, checkout}  = Git.checkout(branch: "feat/new-thing")
checkout.created #=> false

Diffs

{:ok, diff} = Git.diff(stat: true)
diff.total_insertions  #=> 10
diff.total_deletions   #=> 3

{:ok, staged} = Git.diff(staged: true)
staged.raw  #=> full patch text

Remotes

{:ok, remotes} = Git.remote()
hd(remotes).fetch_url  #=> "https://github.com/owner/repo.git"

{:ok, :done} = Git.remote(add_name: "upstream", add_url: "https://github.com/upstream/repo.git")
{:ok, :done} = Git.remote(remove: "upstream")

Tags

{:ok, tags}  = Git.tag()
{:ok, :done} = Git.tag(create: "v1.0.0", message: "First release")
{:ok, :done} = Git.tag(delete: "v0.9.0")

Merging

{:ok, result} = Git.merge("feature-branch")
result.fast_forward       #=> true
result.already_up_to_date #=> false

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

Stashing

{:ok, :done}    = Git.stash(save: true, message: "wip: half-done feature")
{:ok, entries}  = Git.stash()
hd(entries).message  #=> "wip: half-done feature"
{:ok, :done}    = Git.stash(pop: true)

Repository management

{:ok, :done} = Git.init(path: "/tmp/new-repo")
{:ok, :done} = Git.clone("https://github.com/owner/repo.git", depth: 1)
{:ok, :done} = Git.reset(mode: :soft, ref: "HEAD~1")

Summary

Functions

Runs git add to stage files for the next commit.

Runs git am to apply patches from mailbox-formatted files.

Runs git apply to apply a patch to files and/or the index.

Runs git archive to create an archive of files from a named tree.

Runs git bisect to find the commit that introduced a bug.

Runs git blame to show line-by-line authorship of a file.

Runs git branch to list, create, or delete branches.

Runs git bundle to create, verify, list heads of, or unbundle bundles.

Runs git cat-file to provide content or type/size info for repository objects.

Runs git check-attr to report the gitattributes applied to paths.

Runs git check-ignore to test whether paths are ignored by .gitignore.

Runs git check-ref-format to validate (and optionally normalize) a ref.

Runs git checkout to switch branches, create and switch branches, or restore files.

Runs git cherry to find commits not yet applied upstream.

Runs git cherry-pick to apply commits from another branch.

Runs git clean to remove untracked files from the working tree.

Runs git clone to clone a repository.

Runs git commit and returns the parsed output.

Runs git commit-tree to build a commit object directly from a tree.

Runs git count-objects -v and returns a parsed Git.CountObjects struct.

Runs git describe to find the most recent tag reachable from a commit.

Runs git diff and returns parsed diff output.

Runs git diff-files (raw plumbing) to compare the working tree to the index.

Runs git diff-index (raw plumbing) to compare a tree-ish to the index and working tree.

Runs git diff-tree (raw plumbing) to compare two trees.

Runs git fetch to download objects and refs from a remote repository.

Runs git for-each-ref to iterate over refs.

Runs git format-patch to generate patch files from commits.

Runs git fsck to verify connectivity and validity of objects.

Runs git gc to clean up unnecessary files and optimize the repository.

Runs git config to read or write git configuration values.

Runs git grep to search tracked files for a pattern.

Runs git hash-object to compute the object ID for a file.

Runs git init to initialize a new repository.

Runs git interpret-trailers to add or parse trailers in commit messages.

Runs git log and returns the parsed output.

Runs git ls-files to list files in the index and working tree.

Runs git ls-remote to list references in a remote repository.

Runs git ls-tree to list the contents of a tree object.

Runs git maintenance to manage repository maintenance tasks.

Runs git merge to merge a branch or drive an in-progress merge.

Runs git merge-base to find the best common ancestor(s).

Runs git merge-file to perform a scripted three-way merge of three files.

Runs git merge-tree --write-tree to merge two commits in the object database.

Runs git mktree to build a tree object from entries fed on stdin.

Runs git mv to move or rename a tracked file.

Runs git name-rev to find a symbolic name for a commit.

Runs git notes to manage notes attached to objects.

Runs git pull to fetch and integrate changes from a remote repository.

Runs git push to push commits to a remote repository.

Runs git range-diff to compare two sequences of commits.

Runs git read-tree to load tree contents into the index.

Runs git rebase to reapply commits on top of another base.

Runs git reflog to show the reference log.

Runs git remote to list, add, or remove remotes.

Runs git rerere to reuse recorded resolution of conflicted merges.

Runs git reset to move HEAD and optionally modify the index and working tree.

Runs git restore to restore working tree files.

Runs git rev-list to list commit objects.

Runs git rev-parse to resolve refs and query repository information.

Runs git revert to create a commit that undoes a previous commit.

Runs git rm to remove files from the working tree and index.

Runs git shortlog to summarize log output by author.

Runs git show to display information about a git object.

Runs git show-ref to list references in the local repository.

Runs git sparse-checkout to manage sparse-checkout patterns.

Runs git stash to list, save, pop, apply, drop, clear, branch, or show stash entries.

Runs git status and returns the parsed output.

Runs git submodule to manage submodules.

Runs git switch to change branches.

Runs git symbolic-ref to read, create, or delete symbolic refs.

Runs git tag to list, create, or delete tags.

Runs git update-index to populate or modify the index directly.

Runs git update-ref to update the object name stored in a ref.

Runs git var to read git's logical variables.

Runs git verify-commit to check the GPG signature of a commit.

Runs git verify-tag to check the GPG signature of a tag.

Runs git --version and returns a parsed Git.Version struct.

Runs git worktree to manage linked working trees.

Runs git write-tree to record the current index as a tree object.

Functions

add(opts \\ [])

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

Runs git add to stage files for the next commit.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :files - list of file paths to stage (default [])
  • :all - stage all changes including deletions (--all, default false)
  • :update - stage tracked modifications and deletions only (-u, default false)
  • :force - stage ignored files (-f, default false)
  • :dry_run - show what would be staged without staging (-n, default false)
  • :intent_to_add - record intent to add without content (-N, default false)
  • :renormalize - re-apply the clean filter to tracked files (default false)
  • :chmod - set the executable bit, "+x" or "-x" (default nil)

Flags and :files compose, so Git.add(update: true, files: ["lib"]) runs git add --update lib.

am(opts \\ [])

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

Runs git am to apply patches from mailbox-formatted files.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :patches - list of paths to mailbox patch files
  • :directory - path to directory of patches
  • :three_way - 3-way merge on conflict (--3way)
  • :keep - keep subject prefix (--keep)
  • :keep_cr - keep carriage return at line ends (--keep-cr)
  • :signoff - add Signed-off-by line (--signoff)
  • :abort - abort current am session (--abort)
  • :continue_ - continue after resolving conflict (--continue)
  • :skip - skip current patch (--skip)
  • :quiet - quiet output (--quiet)

Examples

Git.am(patches: ["0001-fix.patch"])
Git.am(patches: ["0001-fix.patch"], three_way: true)
Git.am(abort: true)

apply_patch(opts \\ [])

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

Runs git apply to apply a patch to files and/or the index.

The function is named apply_patch to avoid conflicting with Kernel.apply/2.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :patch - path to the patch file (required)
  • :check - check if patch applies cleanly without applying (--check)
  • :stat - show diffstat (--stat)
  • :summary - show summary (--summary)
  • :numstat - show machine-readable added/removed line counts (--numstat)
  • :cached - apply to index only (--cached)
  • :index - apply to index and working tree (--index)
  • :reverse - apply in reverse (--reverse)
  • :three_way - attempt 3-way merge (--3way)
  • :verbose - verbose output (--verbose)

Examples

Git.apply_patch(patch: "fix.patch")
Git.apply_patch(patch: "fix.patch", check: true)
Git.apply_patch(patch: "fix.patch", stat: true)

archive(opts \\ [])

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

Runs git archive to create an archive of files from a named tree.

Creates a tar, tar.gz, or zip archive of the repository contents. The output option is currently required because git writes binary archive data to stdout when no output file is specified, which cannot be reliably captured as a string.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - tree-ish to archive (default "HEAD")
  • :format - archive format: "tar", "tar.gz", or "zip" (--format=)
  • :output - output file path (--output=)
  • :prefix - prepend prefix to each filename (--prefix=)
  • :paths - restrict archive to these paths (after --)
  • :remote - retrieve archive from a remote repository (--remote=)
  • :worktree_attributes - use worktree attributes (--worktree-attributes)
  • :verbose - report progress to stderr (-v)

Examples

Git.archive(output: "/tmp/repo.tar.gz", format: "tar.gz")
Git.archive(output: "/tmp/lib.zip", format: "zip", paths: ["lib/"])
Git.archive(output: "/tmp/v1.tar", ref: "v1.0.0", prefix: "project/")

bisect(opts \\ [])

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

Runs git bisect to find the commit that introduced a bug.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :start - start bisect session
  • :bad - mark ref as bad (or current HEAD if true)
  • :good - mark ref as good (or current HEAD if true)
  • :reset - end bisect session
  • :skip - skip current commit
  • :log - show bisect log
  • :new_ref - alias for bad (newer git)
  • :old_ref - alias for good (newer git)
  • :replay - replay bisect from file

Note: bisect run and bisect visualize are not supported.

Examples

Git.bisect(start: true)
Git.bisect(bad: "HEAD")
Git.bisect(good: "v1.0.0")
Git.bisect(reset: true)

blame(file, opts \\ [])

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

Runs git blame to show line-by-line authorship of a file.

The file path is required as the first argument.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :lines - line range (-L start,end or -L :funcname)
  • :rev - blame at specific revision
  • :show_email - show author email (-e)
  • :show_name - show author name (--show-name)
  • :date - date format (--date=format)
  • :reverse - show reverse blame (--reverse)
  • :first_parent - follow only first parent (--first-parent)
  • :encoding - output encoding (--encoding)
  • :root - do not treat root commits specially (--root)

Examples

Git.blame("lib/my_file.ex")
Git.blame("lib/my_file.ex", lines: "1,10")
Git.blame("lib/my_file.ex", rev: "HEAD~5")

branch(opts \\ [])

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

Runs git branch to list, create, or delete branches.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :create - name of a new branch to create
  • :start_point - commit/ref to create the branch from when using :create (default nil)
  • :delete - name of a branch to delete
  • :force_delete - use -D for delete (default false)
  • :all - include remote-tracking branches in the listing (default false)

bundle(opts \\ [])

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

Runs git bundle to create, verify, list heads of, or unbundle bundles.

Exactly one of :create, :verify, :list_heads, or :unbundle must be set to the bundle file path.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :create - output file path for creating a bundle
  • :verify - bundle file path to verify
  • :list_heads - bundle file path to list heads from
  • :unbundle - bundle file path to unbundle
  • :rev - revision range for create (e.g. "HEAD", "v1.0..v2.0")
  • :all - include all refs (--all, for create)
  • :quiet - suppress output (-q)
  • :progress - show progress (--progress)

Examples

Git.bundle(create: "/tmp/repo.bundle", rev: "HEAD")
Git.bundle(verify: "/tmp/repo.bundle")
Git.bundle(list_heads: "/tmp/repo.bundle")

cat_file(object, opts \\ [])

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

Runs git cat-file to provide content or type/size info for repository objects.

The object (SHA or ref) is required as the first argument.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :type - show object type (-t)
  • :size - show object size (-s)
  • :print - pretty-print object content (-p)
  • :exists - check if object exists (-e); returns {:ok, true} or {:ok, false}
  • :textconv - show content with textconv filter (--textconv)
  • :filters - show content with filters applied (--filters)

Examples

Git.cat_file("HEAD", type: true)
Git.cat_file("abc1234", size: true)
Git.cat_file("HEAD", print: true)
Git.cat_file("deadbeef", exists: true)

check_attr(opts \\ [])

@spec check_attr(keyword()) ::
  {:ok, [Git.Commands.CheckAttr.attribute()]} | {:error, term()}

Runs git check-attr to report the gitattributes applied to paths.

This is the attributes analogue of check_ignore/1. Output is always requested with -z, so paths and values containing spaces or newlines parse unambiguously.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :attrs - list of attribute names to query (required unless :all)
  • :paths - list of paths to check (required)
  • :all - report every attribute set on each path (-a); ignores :attrs
  • :cached - read .gitattributes from the index, not the working tree

Returns {:ok, [%{path: path, attr: attr, value: value}]}. value is the raw info string reported by git: one of "set", "unset", "unspecified", or a custom attribute value.

Examples

Git.check_attr(attrs: ["diff"], paths: ["src/main.ex"])
Git.check_attr(attrs: ["diff", "text"], paths: ["a.ex", "b.png"])
Git.check_attr(all: true, paths: ["src/main.ex"])

check_ignore(opts \\ [])

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

Runs git check-ignore to test whether paths are ignored by .gitignore.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :paths - list of paths to check (required)
  • :verbose - show matching pattern info (-v)
  • :non_matching - also show non-matching paths (-n, requires -v)
  • :no_index - do not look at the index (--no-index)
  • :quiet - suppress output, use exit status only (-q)

Examples

Git.check_ignore(paths: ["build/", "tmp.log"])
Git.check_ignore(paths: ["src/main.ex"], verbose: true)

check_ref_format(opts \\ [])

@spec check_ref_format(keyword()) ::
  {:ok, true | String.t()} | {:error, :invalid_ref | term()}

Runs git check-ref-format to validate (and optionally normalize) a ref.

Returns {:ok, true} for a valid ref, {:ok, normalized} when :normalize or :branch is set (the normalized/expanded ref), or {:error, :invalid_ref} when the ref is not well-formed.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - the ref (or branch shorthand) to check (required)
  • :normalize - normalize the ref and print it (--normalize)
  • :branch - validate a branch-name shorthand (--branch)
  • :allow_onelevel - accept single-level refs like HEAD (--allow-onelevel)

Examples

Git.check_ref_format(ref: "refs/heads/main")            #=> {:ok, true}
Git.check_ref_format(ref: "refs/heads//main", normalize: true)
Git.check_ref_format(ref: "bad name")                   #=> {:error, :invalid_ref}

checkout(opts \\ [])

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

Runs git checkout to switch branches, create and switch branches, or restore files.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :branch - name of the branch to switch to
  • :create - when true, creates the branch before switching (-b flag, default false)
  • :start_point - commit/ref to create the branch from when using :create (default nil)
  • :files - list of file paths to restore from the index (default [])

cherry(opts \\ [])

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

Runs git cherry to find commits not yet applied upstream.

Returns a list of Git.CherryEntry structs. Each entry indicates whether a commit has already been applied upstream and includes the SHA (and subject when verbose: true).

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :upstream - upstream branch (required)
  • :head - head branch (default: HEAD)
  • :limit - limit ref
  • :verbose - include commit subject (-v)

Examples

Git.cherry(upstream: "main")
Git.cherry(upstream: "main", head: "feature", verbose: true)

cherry_pick(opts \\ [])

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

Runs git cherry-pick to apply commits from another branch.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :commits - list of commit SHAs or refs to cherry-pick
  • :no_commit - apply without committing (--no-commit)
  • :abort - abort in-progress cherry-pick (--abort)
  • :continue_pick - continue after conflict resolution (--continue)
  • :skip - skip current commit (--skip)
  • :mainline - parent number for merge commits (-m)
  • :signoff - add Signed-off-by (--signoff)
  • :allow_empty - allow empty commits (--allow-empty)
  • :strategy - merge strategy (--strategy)
  • :strategy_option - strategy option (--strategy-option)

Note: --edit is not supported as it requires an editor.

Examples

Git.cherry_pick(commits: ["abc1234"])
Git.cherry_pick(commits: ["abc1234", "def5678"], no_commit: true)
Git.cherry_pick(abort: true)

clean(opts \\ [])

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

Runs git clean to remove untracked files from the working tree.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :force - required for actual removal (-f)
  • :directories - also remove untracked directories (-d)
  • :ignored - also remove ignored files (-x)
  • :only_ignored - only remove ignored files (-X)
  • :dry_run - show what would be removed (-n)
  • :exclude - exclude pattern (-e)
  • :quiet - suppress output (-q)
  • :paths - paths to clean

Examples

Git.clean(dry_run: true)
Git.clean(force: true, directories: true)

clone(url, opts \\ [])

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

Runs git clone to clone a repository.

The :config working directory determines where the clone is created.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :depth - create a shallow clone with the given number of commits (--depth)
  • :branch - check out the given branch after cloning (--branch)
  • :directory - name of the target directory (default: inferred from the URL)
  • :filter - partial clone filter spec, e.g. "blob:none" (--filter)
  • :sparse - initialize a sparse-checkout (--sparse, default false)
  • :single_branch - clone only the history of the checked-out branch (default false)
  • :no_checkout - do not check out HEAD after cloning (default false)
  • :bare - create a bare repository (default false)
  • :mirror - set up a mirror of the source (default false)
  • :recurse_submodules - initialize and clone submodules (default false)
  • :origin - name for the source remote instead of origin (--origin)
  • :set_config - list of {key, value} config to set in the new repo (--config)

Examples

Git.clone("https://github.com/owner/repo.git")
Git.clone("https://github.com/owner/repo.git", depth: 1)
Git.clone("https://github.com/owner/repo.git", branch: "main", directory: "my-repo")

commit(message \\ nil, opts \\ [])

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

Runs git commit and returns the parsed output.

The message may be nil for message-less commits such as Git.commit(nil, amend: true, no_edit: true) or when using :file.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :all - stage tracked changes before committing (-a, default false)
  • :amend - amend the previous commit (default false)
  • :allow_empty - allow a commit with no changes (default false)
  • :no_verify - skip the pre-commit and commit-msg hooks (default false)
  • :no_edit - reuse the existing message without opening an editor (default false)
  • :signoff - add a Signed-off-by trailer (-s, default false)
  • :sign - GPG-sign the commit; true uses the configured signing key (-S) or a keyid string signs with that key (-S<keyid>, default false)
  • :author - override the author, "Name <email>" (default nil)
  • :date - override the author date (default nil)
  • :fixup - create a fixup! commit for the given commit (default nil)
  • :squash - create a squash! commit for the given commit (default nil)
  • :file - read the message from a file (-F, default nil)
  • :reuse_message - reuse the message from the given commit (-C, default nil)
  • :cleanup - message cleanup mode (default nil)
  • :only - commit only the listed paths (--only, default [])

Examples

Git.commit("feat: add thing")
Git.commit(nil, amend: true, no_edit: true)
Git.commit("chore: sign", signoff: true)
Git.commit("feat: signed", sign: true)

commit_tree(opts \\ [])

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

Runs git commit-tree to build a commit object directly from a tree.

Plumbing command. Does not touch the index, working tree, or HEAD. The new commit lives only as a loose object until referenced from a ref via update_ref/1. Returns the new commit's SHA on success.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :tree - the tree SHA to commit (required)
  • :parents - list of parent commit SHAs (default: [])
  • :message - commit message, single string (-m)
  • :messages - list of messages, each becomes a separate -m (concatenated as paragraphs in the resulting commit message)
  • :sign - true for -S (use the configured signing key) or a string keyid for -S<keyid>
  • :no_gpg_sign - --no-gpg-sign (overrides commit.gpgSign config)

Examples

Git.commit_tree(tree: tree_sha, message: "thread: open")
Git.commit_tree(tree: tree_sha, parents: [head], message: "next", sign: true)
Git.commit_tree(tree: tree_sha, parents: [a, b], message: "merge")

count_objects(opts \\ [])

@spec count_objects(keyword()) :: {:ok, Git.CountObjects.t()} | {:error, term()}

Runs git count-objects -v and returns a parsed Git.CountObjects struct.

Reports loose- and packed-object counts and on-disk sizes (sizes in KiB).

Options

  • :config - a Git.Config struct (default: Git.Config.new())

Examples

{:ok, stats} = Git.count_objects()
stats.count    #=> 3
stats.in_pack  #=> 0

describe(opts \\ [])

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

Runs git describe to find the most recent tag reachable from a commit.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - commit to describe (default: nil, describes HEAD)
  • :tags - use any tag, not just annotated (--tags)
  • :all - use any ref (--all)
  • :long - always use long format (--long)
  • :first_parent - follow only first parent (--first-parent)
  • :abbrev - abbreviation length (--abbrev=N)
  • :exact_match - only output exact matches (--exact-match)
  • :dirty - describe with dirty suffix (--dirty or --dirty=MARK)
  • :always - show abbreviated commit if no tag found (--always)
  • :match - only consider tags matching glob (--match=)
  • :exclude - exclude tags matching glob (--exclude=)
  • :candidates - number of candidate tags to consider (--candidates=N)
  • :broken - describe broken working tree as broken (--broken)

Examples

Git.describe(tags: true)
Git.describe(always: true, abbrev: 7)
Git.describe(exact_match: true, ref: "v1.0")

diff(opts \\ [])

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

Runs git diff and returns parsed diff output.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :staged - show staged (cached) diff (default false)
  • :stat - return file-level stats instead of full patch (default false)
  • :numstat - machine-readable per-file insertion/deletion counts, parsed into files with exact counts (default false)
  • :name_only - list only file paths (default false)
  • :name_status - list file paths with status letters (default false)
  • :ignore_all_space - ignore all whitespace (-w, default false)
  • :ignore_space_change - ignore changes in amount of whitespace (-b, default false)
  • :ignore_space_at_eol - ignore whitespace at end of line (default false)
  • :find_renames - detect renames (-M, default false)
  • :find_copies - detect copies (-C, default false)
  • :reverse - swap the two sides of the diff (-R, default false)
  • :unified - number of context lines (-U<n>, default nil)
  • :diff_filter - select changes by type, e.g. "ACMR" (--diff-filter, default nil)
  • :ref - compare against this ref (e.g., "HEAD~1")
  • :ref_end - second ref for two-ref comparisons (requires :ref)
  • :path - limit the diff to this path

diff_files(opts \\ [])

@spec diff_files(keyword()) :: {:ok, [Git.DiffRawEntry.t()]} | {:error, term()}

Runs git diff-files (raw plumbing) to compare the working tree to the index.

Emits --raw -z and returns {:ok, [Git.DiffRawEntry.t()]}.

Options

  • :config - a Git.Config struct (default: Git.Config.new())

Examples

Git.diff_files()

diff_index(opts \\ [])

@spec diff_index(keyword()) ::
  {:ok, [Git.DiffRawEntry.t()] | boolean()} | {:error, term()}

Runs git diff-index (raw plumbing) to compare a tree-ish to the index and working tree.

In the default (raw) mode, emits --raw -z and returns {:ok, [Git.DiffRawEntry.t()]}. With :quiet, runs as a dirty-check: returns {:ok, true} when there are differences and {:ok, false} when there are none.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :tree_ish - the tree-ish to compare against (default "HEAD")
  • :cached - compare against the index only (--cached, default false)
  • :quiet - dirty-check mode returning a boolean (--quiet, default false)

Examples

Git.diff_index(cached: true)
Git.diff_index(quiet: true)

diff_tree(opts \\ [])

@spec diff_tree(keyword()) :: {:ok, [Git.DiffRawEntry.t()]} | {:error, term()}

Runs git diff-tree (raw plumbing) to compare two trees.

Emits --raw -z and parses each record into a Git.DiffRawEntry. With a single tree-ish, diffs a commit against its first parent (the leading commit-id header git prints is skipped).

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :tree_ish - the first (or only) tree-ish to diff (default "HEAD")
  • :tree_ish2 - a second tree-ish; when set, diffs tree_ish tree_ish2
  • :recursive - recurse into subtrees (-r, default false)
  • :find_renames - detect renames (-M, default false)

Examples

Git.diff_tree(tree_ish: "HEAD~1", tree_ish2: "HEAD", recursive: true)
Git.diff_tree(tree_ish: "HEAD")

fetch(opts \\ [])

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

Runs git fetch to download objects and refs from a remote repository.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :remote - remote name
  • :branch - refspec to fetch
  • :all - fetch all remotes (--all)
  • :prune - prune deleted remote branches (--prune)
  • :prune_tags - prune tags (--prune-tags)
  • :tags / :no_tags - fetch tags behavior
  • :depth - shallow fetch depth (--depth)
  • :unshallow - convert shallow to complete (--unshallow)
  • :dry_run - dry run (--dry-run)
  • :force - force update refs (--force)
  • :verbose / :quiet - output verbosity
  • :jobs - number of parallel jobs (--jobs)
  • :recurse_submodules - recurse into submodules (true or strategy string)
  • :set_upstream - set upstream tracking (--set-upstream)
  • :refspecs - list of raw [+]<src>:<dst> refspecs appended after the remote (default [])

Examples

Git.fetch()
Git.fetch(remote: "origin", prune: true)
Git.fetch(all: true, tags: true)
Git.fetch(remote: "origin", refspecs: ["+main:refs/remotes/origin/main"])

for_each_ref(opts \\ [])

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

Runs git for-each-ref to iterate over refs.

Iterates over all refs matching the given pattern(s) and formats them according to the given format string.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :format - output format string (--format)
  • :sort - sort key or list of keys (--sort)
  • :count - limit number of results (--count)
  • :pattern - ref pattern(s) to match (positional args)
  • :contains - only refs containing commit (--contains)
  • :merged - only refs merged into ref (--merged)
  • :no_merged - only refs not merged into ref (--no-merged)
  • :points_at - only refs pointing at object (--points-at)

Examples

Git.for_each_ref(pattern: "refs/heads/", format: "%(refname:short)")
Git.for_each_ref(sort: "-creatordate", count: 5)

format_patch(opts \\ [])

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

Runs git format-patch to generate patch files from commits.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - revision range (required, e.g. "HEAD~3", "v1.0..v2.0")
  • :output_directory - output directory (-o)
  • :numbered - number patches in subject (-n)
  • :cover_letter - generate cover letter (--cover-letter)
  • :stdout - output patches to stdout (--stdout)
  • :from - set From header (--from=)
  • :subject_prefix - subject prefix (--subject-prefix=)
  • :no_stat - suppress diffstat (--no-stat)
  • :start_number - start numbering at N (--start-number=N)
  • :signature - signature string (--signature=)
  • :no_signature - suppress signature (--no-signature)
  • :quiet - suppress output of file names (-q)
  • :zero_commit - use zero commit hash in From header (--zero-commit)
  • :base - record base tree info (--base=)

Examples

Git.format_patch(ref: "HEAD~3", output_directory: "/tmp/patches")
Git.format_patch(ref: "v1.0..v2.0", stdout: true)

fsck(opts \\ [])

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

Runs git fsck to verify connectivity and validity of objects.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :full - check objects in all packs and alternate objects (--full)
  • :strict - enable stricter checking (--strict)
  • :unreachable - report unreachable objects (--unreachable)
  • :dangling - report dangling objects (--dangling)
  • :no_dangling - suppress dangling object warnings (--no-dangling)
  • :no_reflogs - do not consider reflog entries (--no-reflogs)
  • :connectivity_only - only check connectivity (--connectivity-only)
  • :root - report root nodes (--root)
  • :lost_found - write dangling objects into .git/lost-found (--lost-found)
  • :name_objects - name objects for easier identification (--name-objects)
  • :verbose - be verbose (--verbose)
  • :progress - show progress (--progress)
  • :no_progress - suppress progress (--no-progress)

Examples

Git.fsck()
Git.fsck(full: true, strict: true)
Git.fsck(unreachable: true, no_reflogs: true)

gc(opts \\ [])

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

Runs git gc to clean up unnecessary files and optimize the repository.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :aggressive - more aggressive optimization (--aggressive)
  • :auto - only run if housekeeping is needed (--auto)
  • :prune - prune loose objects older than date (--prune=<date>)
  • :no_prune - do not prune any loose objects (--no-prune)
  • :quiet - suppress progress output (--quiet)
  • :force - force gc even if another gc may be running (--force)
  • :keep_largest_pack - keep the largest pack (--keep-largest-pack)

Examples

Git.gc()
Git.gc(aggressive: true)
Git.gc(auto: true)
Git.gc(prune: "now")

git_config(opts \\ [])

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

Runs git config to read or write git configuration values.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :get - key to read
  • :set_key - key to set (requires :set_value)
  • :set_value - value to set (requires :set_key)
  • :unset - key to unset
  • :list - list all config (--list)
  • :global - use global config (--global)
  • :local - use local config (--local)
  • :system - use system config (--system)
  • :get_regexp - get keys matching pattern (--get-regexp)
  • :add - add value for multi-valued key (--add)
  • :type - type constraint (--type)
  • :default - default value for get (--default)
  • :name_only - show only key names (--name-only)

Examples

Git.git_config(get: "user.name")
Git.git_config(set_key: "user.name", set_value: "Test User", local: true)
Git.git_config(list: true, global: true)

grep(pattern, opts \\ [])

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

Runs git grep to search tracked files for a pattern.

The search pattern is required as the first argument.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :paths - list of paths to restrict search to
  • :line_number - show line numbers (-n, default true)
  • :count - show count per file (-c)
  • :files_with_matches - show only filenames with matches (-l)
  • :files_without_match - show only filenames without matches (-L)
  • :ignore_case - case insensitive search (-i)
  • :word_regexp - match whole words only (-w)
  • :extended_regexp - use extended regex (-E)
  • :fixed_strings - treat pattern as fixed string (-F)
  • :perl_regexp - use Perl-compatible regex (-P)
  • :invert_match - show non-matching lines (--invert-match)
  • :max_count - max matches per file (-m)
  • :context - show context lines (-C)
  • :before_context - show lines before match (-B)
  • :after_context - show lines after match (-A)
  • :show_function - show surrounding function (-p)
  • :heading - show filename as heading (--heading)
  • :break - add blank line between file results (--break)
  • :untracked - also search untracked files (--untracked)
  • :no_index - search files not managed by git (--no-index)
  • :recurse_submodules - search in submodules (--recurse-submodules)
  • :quiet - suppress output, exit with status (-q)
  • :all_match - require all patterns to match (--all-match)
  • :ref - search in a specific ref (e.g. "HEAD", "v1.0")

Examples

Git.grep("defmodule")
Git.grep("TODO", ignore_case: true)
Git.grep("hello", files_with_matches: true)
Git.grep("pattern", ref: "HEAD~5", paths: ["lib/"])

hash_object(opts \\ [])

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

Runs git hash-object to compute the object ID for a file.

Computes the object ID value for a file and optionally writes it into the object database. Only file-based hashing is supported.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :file - path to the file to hash
  • :write - write the object into the database (-w)
  • :type - object type (-t, default "blob")
  • :literally - allow hashing malformed objects (--literally)

Examples

Git.hash_object(file: "README.md")
Git.hash_object(file: "README.md", write: true)

init(opts \\ [])

@spec init(keyword()) :: {:ok, :done} | {:error, term()}

Runs git init to initialize a new repository.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :path - directory to initialize (default: the working directory)
  • :bare - when true, initializes a bare repository (--bare flag, default false)

interpret_trailers(opts \\ [])

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

Runs git interpret-trailers to add or parse trailers in commit messages.

Trailers are key-value metadata lines at the end of commit messages, such as "Signed-off-by:" or "Co-authored-by:".

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :file - path to a file containing the commit message
  • :parse - only output the trailers (--only-trailers)
  • :trailers - list of trailers to add, each as "Key: Value" (--trailer)
  • :in_place - edit the file in place (--in-place)
  • :trim_empty - trim empty trailers (--trim-empty)
  • :where - where to place new trailers: "after", "before", "end", "start" (--where)
  • :if_exists - action if trailer exists: "addIfDifferentNeighbor", "addIfDifferent", "add", "replace", "doNothing" (--if-exists)
  • :if_missing - action if trailer missing: "add", "doNothing" (--if-missing)
  • :unfold - unfold multi-line trailers (--unfold)
  • :no_divider - do not treat --- as divider (--no-divider)

Examples

Git.interpret_trailers(file: "msg.txt", trailers: ["Signed-off-by: Name <email>"])
Git.interpret_trailers(file: "msg.txt", parse: true)
Git.interpret_trailers(file: "msg.txt", trailers: ["Acked-by: Name"], in_place: true)

log(opts \\ [])

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

Runs git log and returns the parsed output.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • All other options are passed to the underlying command.

ls_files(opts \\ [])

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

Runs git ls-files to list files in the index and working tree.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :cached - show cached files (--cached)
  • :deleted - show deleted files (--deleted)
  • :modified - show modified files (--modified)
  • :others - show untracked files (--others)
  • :ignored - show ignored files (--ignored)
  • :stage - show staged info (-s)
  • :unmerged - show unmerged files (-u)
  • :exclude_standard - use standard exclusions (--exclude-standard)
  • :exclude - exclude pattern (--exclude)
  • :full_name - show full paths (--full-name)
  • :paths - filter by paths

Examples

Git.ls_files()
Git.ls_files(others: true, exclude_standard: true)
Git.ls_files(modified: true)

ls_remote(opts \\ [])

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

Runs git ls-remote to list references in a remote repository.

Returns a list of Git.LsRemoteEntry structs containing the SHA and ref name for each reference in the remote.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :remote - remote name or URL (default: origin)
  • :heads - show only heads (--heads)
  • :tags - show only tags (--tags)
  • :refs - pattern to filter refs
  • :sort - sort key (--sort=)
  • :symref - show underlying ref for symbolic refs (--symref)
  • :quiet - suppress output, exit with status only (-q)
  • :exit_code - exit with status 2 when no matching refs (--exit-code)

Examples

Git.ls_remote(remote: "origin")
Git.ls_remote(heads: true)
Git.ls_remote(tags: true, remote: "https://github.com/owner/repo.git")

ls_tree(opts \\ [])

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

Runs git ls-tree to list the contents of a tree object.

Returns a list of Git.TreeEntry structs with mode, type, SHA, path, and optionally size. When :name_only is true, returns a list of path strings instead.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - tree-ish to list (default "HEAD")
  • :recursive - recurse into subtrees (-r)
  • :tree_only - show only tree entries, not blobs (-d)
  • :long - include object size (-l/--long)
  • :name_only - show only paths (--name-only)
  • :abbrev - abbreviate SHA to N characters (--abbrev=N)
  • :full_name - show full path names (--full-name)
  • :full_tree - show full tree regardless of current directory (--full-tree)
  • :path - restrict to this path (after --)

Examples

Git.ls_tree()
Git.ls_tree(recursive: true)
Git.ls_tree(name_only: true, ref: "main")
Git.ls_tree(long: true, path: "lib/")

maintenance(opts \\ [])

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

Runs git maintenance to manage repository maintenance tasks.

Supports running, starting, stopping, registering, and unregistering maintenance tasks such as garbage collection and commit-graph updates.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :run - run maintenance tasks (run subcommand)
  • :start - start background maintenance (start subcommand)
  • :stop - stop background maintenance (stop subcommand)
  • :register_ - register repo for maintenance (register subcommand)
  • :unregister - unregister repo from maintenance (unregister subcommand)
  • :task - specific task to run (--task)
  • :auto - only run if needed (--auto)
  • :quiet - suppress output (--quiet)
  • :schedule - maintenance schedule: "hourly", "daily", "weekly" (--schedule)

Examples

Git.maintenance(run: true)
Git.maintenance(run: true, task: "gc")
Git.maintenance(run: true, auto: true)
Git.maintenance(start: true)
Git.maintenance(stop: true)

merge(branch_or_action, opts \\ [])

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

Runs git merge to merge a branch or drive an in-progress merge.

Pass a branch name to merge it into the current branch. Pass :abort, :continue, or :quit to drive an in-progress merge.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :no_ff - force a merge commit even for fast-forward merges (default false)
  • :ff_only - refuse to merge unless it can fast-forward (default false)
  • :squash - squash the merged commits into the index (default false)
  • :no_commit - merge but do not create the merge commit (default false)
  • :no_edit - accept the auto-generated merge message (default false)
  • :allow_unrelated_histories - merge histories with no common ancestor (default false)
  • :verify_signatures - refuse to merge unless the tip commit is signed and valid (--verify-signatures, default false)
  • :gpg_sign - GPG-sign the merge commit; true uses the configured signing key (-S) or a keyid string signs with that key (-S<keyid>, default false)
  • :message - merge commit message (-m, default nil)
  • :strategy - merge strategy (-s, default nil)
  • :strategy_option - list of strategy options (-X, repeatable, default [])

Examples

Git.merge("feature-branch")
Git.merge("feature-branch", no_ff: true)
Git.merge("feature-branch", strategy_option: ["ours"])
Git.merge(:abort)
Git.merge(:continue)
Git.merge(:quit)

merge_base(opts \\ [])

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

Runs git merge-base to find the best common ancestor(s).

By default returns a single ancestor SHA. With is_ancestor: true, returns a boolean indicating whether the first commit is an ancestor of the second. With all: true or independent: true, returns a list of SHAs.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :commits - list of commit refs to compare (two or more)
  • :is_ancestor - check if first is ancestor of second (--is-ancestor)
  • :fork_point - find fork point (--fork-point)
  • :octopus - find octopus merge base (--octopus)
  • :all - output all merge bases (--all)
  • :independent - list independent commits (--independent)

Examples

Git.merge_base(commits: ["main", "feature"])
Git.merge_base(commits: ["main", "feature"], is_ancestor: true)
Git.merge_base(commits: ["main", "feature"], all: true)

merge_file(current, base, other, opts \\ [])

@spec merge_file(String.t(), String.t(), String.t(), keyword()) ::
  {:ok, non_neg_integer()} | {:error, term()}

Runs git merge-file to perform a scripted three-way merge of three files.

Incorporates the changes that lead from base to other into current, writing the merged result (with conflict markers where the two sides overlap) back into the current file. This works purely on files on disk; the index and history are not touched.

Returns {:ok, count} where count is the number of conflicts (0 for a clean merge). A real error (bad option, missing file) returns {:error, {stdout, exit_code}}.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :quiet - do not warn about conflicts (-q, default false)
  • :ours - resolve conflicts in favor of current (--ours, default false)
  • :theirs - resolve conflicts in favor of other (--theirs, default false)
  • :union - resolve conflicts by keeping both sides (--union, default false)
  • :diff3 - use a diff3-based merge with base markers (--diff3, default false)
  • :zdiff3 - use a zealous diff3-based merge (--zdiff3, default false)
  • :marker_size - conflict marker length (--marker-size, default nil)
  • :labels - up to three labels applied to current, base, other conflict markers, in order (-L, default [])

Examples

Git.merge_file("current.txt", "base.txt", "other.txt")
Git.merge_file("current.txt", "base.txt", "other.txt", ours: true)
Git.merge_file("current.txt", "base.txt", "other.txt", labels: ["ours", "base", "theirs"])

merge_tree(branch1, branch2, opts \\ [])

@spec merge_tree(String.t(), String.t(), keyword()) ::
  {:ok, Git.MergeTreeResult.t()} | {:error, term()}

Runs git merge-tree --write-tree to merge two commits in the object database.

Plumbing command. Performs a three-way merge of branch1 and branch2 with no checkout, index, or working tree, and returns a Git.MergeTreeResult with the merged tree SHA, whether the merge was clean, and any conflicted paths. Useful for CI mergeability checks and server-side merges.

A merge with conflicts is returned as {:ok, %Git.MergeTreeResult{clean: false}}, not an error. Requires git 2.38 or newer.

Options

  • :config - a Git.Config struct (default: Git.Config.new())

Examples

{:ok, result} = Git.merge_tree("main", "feature")
result.clean      #=> true
result.tree       #=> "5b12e6a..."
result.conflicts  #=> []

mktree(opts \\ [])

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

Runs git mktree to build a tree object from entries fed on stdin.

Plumbing command. Returns the new tree's SHA, with no index or working tree. With hash_object and commit_tree, synthesizes trees and commits purely from object SHAs. Reads stdin, so it needs the default forcola runner.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :entries - list of %{mode, type, object, path} maps
  • :missing - --missing, allow entries pointing at missing objects (default false)

Examples

{:ok, tree} =
  Git.mktree(entries: [%{mode: "100644", type: "blob", object: blob_sha, path: "a.txt"}])

mv(source, destination, opts \\ [])

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

Runs git mv to move or rename a tracked file.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :force - force move (-f)
  • :dry_run - dry run (-n)
  • :verbose - verbose output (-v)
  • :skip_errors - skip errors (-k)

Examples

Git.mv("old_name.ex", "new_name.ex")
Git.mv("old_name.ex", "new_name.ex", force: true)

name_rev(opts \\ [])

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

Runs git name-rev to find a symbolic name for a commit.

Returns the symbolic name string. With :name_only the output is just the name; otherwise git prefixes it with the input revision.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :commit - the commit to name (required)
  • :name_only - print only the name, without the input (--name-only)
  • :tags - only use tags to name the commit (--tags)

Examples

Git.name_rev(commit: "HEAD", name_only: true)
Git.name_rev(commit: "abc123", name_only: true, tags: true)

notes(opts \\ [])

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

Runs git notes to manage notes attached to objects.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :list - list notes (default true)
  • :show - show note for a ref (string)
  • :add - add a note (boolean)
  • :append - append to an existing note (boolean)
  • :message - note message (-m, for add/append)
  • :ref - commit ref for add/append/show
  • :force - overwrite existing note (-f)
  • :remove - remove note from ref (string)
  • :prune - prune notes for unreachable objects (boolean)
  • :notes_ref - use alternate notes ref (--ref=)

Note: notes edit is not supported because it launches an interactive editor.

Examples

Git.notes()
Git.notes(show: "HEAD")
Git.notes(add: true, message: "review passed", ref: "HEAD")
Git.notes(remove: "HEAD")

pull(opts \\ [])

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

Runs git pull to fetch and integrate changes from a remote repository.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :remote - remote name
  • :branch - branch to pull
  • :rebase - rebase instead of merge (true, or a strategy string)
  • :ff_only - fast-forward only (--ff-only)
  • :no_ff - create merge commit (--no-ff)
  • :autostash - autostash before operation (--autostash)
  • :squash - squash commits (--squash)
  • :no_commit - merge without committing (--no-commit)
  • :depth - limit fetch depth (--depth)
  • :dry_run - dry run (--dry-run)
  • :tags / :no_tags - fetch tags behavior
  • :prune - prune deleted remote branches (--prune)
  • :verbose / :quiet - output verbosity

Examples

Git.pull()
Git.pull(remote: "origin", branch: "main")
Git.pull(rebase: true, autostash: true)

push(opts \\ [])

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

Runs git push to push commits to a remote repository.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :remote - remote name (e.g., "origin")
  • :branch - branch or refspec to push
  • :force - force push (--force)
  • :force_with_lease - safer force push; true emits --force-with-lease, a string emits --force-with-lease=<value> (e.g. "main:abc123")
  • :set_upstream - set upstream tracking (-u)
  • :tags - push tags (--tags)
  • :delete - delete remote branch (--delete)
  • :dry_run - dry run (--dry-run)
  • :all - push all branches (--all)
  • :no_verify - skip pre-push hooks (--no-verify)
  • :atomic - atomic push (--atomic)
  • :prune - prune remote branches (--prune)
  • :follow_tags - push annotated tags reachable from the pushed refs (--follow-tags)
  • :signed - GPG-sign the push (--signed)
  • :push_option - list of strings, each emitted as --push-option <value> (default [])
  • :refspecs - list of raw [+]<src>:<dst> refspecs appended after the remote, e.g. ["main:release"] or [":stale"] to delete (default [])

Examples

Git.push(remote: "origin", branch: "main")
Git.push(remote: "origin", branch: "main", force_with_lease: true)
Git.push(remote: "origin", branch: "main", force_with_lease: "main:abc123")
Git.push(remote: "origin", refspecs: ["main:release"])
Git.push(tags: true)
Git.push(remote: "origin", branch: "main", push_option: ["ci.skip"])

range_diff(opts \\ [])

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

Runs git range-diff to compare two sequences of commits.

Supports both the two-range form (using range1 and range2) and the three-argument form (using rev1, rev2, and rev3).

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :range1 - first revision range (e.g. "main..topic-v1")
  • :range2 - second revision range (e.g. "main..topic-v2")
  • :rev1 - base revision (three-arg form)
  • :rev2 - first revision (three-arg form)
  • :rev3 - second revision (three-arg form)
  • :stat - show diffstat (--stat)
  • :no_patch - suppress diff output (--no-patch)
  • :creation_factor - percentage for matching commits (--creation-factor=N)
  • :no_dual_color - disable dual-color mode (--no-dual-color)
  • :left_only - show only left-side commits (--left-only)
  • :right_only - show only right-side commits (--right-only)
  • :no_notes - do not show notes (--no-notes)

Examples

Git.range_diff(range1: "main..topic-v1", range2: "main..topic-v2")
Git.range_diff(rev1: "main", rev2: "topic-v1", rev3: "topic-v2")
Git.range_diff(range1: "main..v1", range2: "main..v2", stat: true)

read_tree(opts \\ [])

@spec read_tree(keyword()) :: {:ok, :done} | {:error, term()}

Runs git read-tree to load tree contents into the index.

Plumbing command. The read side of the index/tree pipeline behind commit_tree/write_tree.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :trees - the tree-ish arguments to read (default [])
  • :merge - -m, a two/three-way in-index merge (default false)
  • :reset - --reset (default false)
  • :update - -u, also update the working tree (default false)
  • :prefix - --prefix, read into a subdirectory of the index

Examples

Git.read_tree(trees: ["HEAD"])
Git.read_tree(trees: ["a", "b"], merge: true, update: true)

rebase(opts \\ [])

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

Runs git rebase to reapply commits on top of another base.

Pass an upstream ref as the first argument, or use keyword options for abort/continue/skip operations.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :upstream - the upstream branch to rebase onto
  • :branch - the branch to rebase (optional)
  • :onto - rebase onto a specific ref (--onto)
  • :abort - abort in-progress rebase (--abort)
  • :continue_rebase - continue after conflict resolution (--continue)
  • :skip - skip current patch (--skip)
  • :quit - abandon the rebase without resetting HEAD (--quit)
  • :autostash - automatically stash/unstash (--autostash)
  • :autosquash / :no_autosquash - autosquash fixup commits
  • :keep_empty / :no_keep_empty - keep empty commits
  • :rebase_merges - recreate merge commits (--rebase-merges)
  • :force_rebase - force rebase (--force-rebase)
  • :verbose / :quiet - output verbosity
  • :stat / :no_stat - show diffstat
  • :exec - run a shell command after each commit (--exec)
  • :update_refs - update branches that point to rebased commits (--update-refs)
  • :strategy - use the given merge strategy (--strategy)
  • :strategy_option - list of strategy-specific options, each passed as --strategy-option <value>
  • :root - rebase all commits reachable from the branch (--root)
  • :empty - how to handle commits that become empty (--empty=<mode>)

Note: --interactive is not supported as it requires an editor. Because of that, :autosquash and :no_autosquash are inert; git only honors --autosquash together with an interactive rebase.

Examples

Git.rebase(upstream: "main")
Git.rebase(upstream: "main", autostash: true)
Git.rebase(abort: true)

reflog(opts \\ [])

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

Runs git reflog to show the reference log.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - ref to show reflog for (default: HEAD)
  • :max_count - limit number of entries (-n)
  • :all - show reflog for all refs (--all)
  • :date - date format (--date=format)

Examples

Git.reflog()
Git.reflog(max_count: 10)
Git.reflog(ref: "main")

remote(opts \\ [])

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

Runs git remote to list, add, or remove remotes.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :add_name - name for a new remote (requires :add_url)
  • :add_url - URL for a new remote (requires :add_name)
  • :remove - name of remote to remove
  • :verbose - verbose listing (default true)

rerere(opts \\ [])

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

Runs git rerere to reuse recorded resolution of conflicted merges.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :status - show files with recorded resolution (default when no subcommand)
  • :diff - show diff of current resolution against recorded resolution
  • :clear - clear all recorded resolutions
  • :forget - forget resolution for a specific path (string)
  • :gc - prune old recorded resolutions
  • :remaining - show files that still need resolution

Examples

Git.rerere()
Git.rerere(status: true)
Git.rerere(diff: true)
Git.rerere(clear: true)
Git.rerere(forget: "path/to/file")
Git.rerere(gc: true)
Git.rerere(remaining: true)

reset(opts \\ [])

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

Runs git reset to move HEAD and optionally modify the index and working tree.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - the ref to reset to (default: "HEAD")
  • :mode - one of :soft, :mixed (default), :hard, :merge, or :keep (ignored when :files is given)
  • :files - a list of paths to unstage via git reset <ref> -- <paths>
  • :quiet - pass -q (default false)

Examples

Git.reset()
Git.reset(mode: :soft, ref: "HEAD~1")
Git.reset(mode: :hard)
Git.reset(files: ["lib/foo.ex"])

restore(opts \\ [])

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

Runs git restore to restore working tree files.

git restore is the modern (Git 2.23+) replacement for the file-restoration role of git checkout. It provides explicit control over restoring from the index (staged) vs a source commit.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :files - list of file paths to restore
  • :staged - restore staged files (unstage, --staged)
  • :worktree - restore working tree files (--worktree)
  • :source - restore from a specific commit/ref (--source)
  • :ours - use our version during conflict (--ours)
  • :theirs - use their version during conflict (--theirs)
  • :patch - interactively select hunks (--patch)

Examples

Git.restore(files: ["README.md"])
Git.restore(files: ["lib/foo.ex"], staged: true)
Git.restore(files: ["lib/foo.ex"], source: "HEAD~1")
Git.restore(files: ["lib/foo.ex"], staged: true, worktree: true)

rev_list(opts \\ [])

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

Runs git rev-list to list commit objects.

Returns a list of SHAs by default. With count: true returns an integer. With left_right: true and count: true returns a map with :left and :right counts.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - rev range (e.g. "HEAD", "main..feature")
  • :max_count - limit number of commits (--max-count=N)
  • :skip - skip N commits (--skip=N)
  • :count - output a count instead of SHAs (--count)
  • :left_right - mark which side of a symmetric diff (--left-right)
  • :ancestry_path - only show commits on the ancestry path (--ancestry-path)
  • :first_parent - follow only first parent (--first-parent)
  • :merges - only show merge commits (--merges)
  • :no_merges - exclude merge commits (--no-merges)
  • :reverse - reverse output order (--reverse)
  • :since - show commits after date (--since=)
  • :until_date - show commits before date (--until=)
  • :author - filter by author (--author=)
  • :all - list objects from all refs (--all)
  • :objects - list objects, not just commits (--objects)
  • :no_walk - do not traverse ancestors (--no-walk)

Examples

Git.rev_list(ref: "HEAD", max_count: 10)
Git.rev_list(ref: "main..feature", count: true)
Git.rev_list(ref: "main...feature", left_right: true, count: true)

rev_parse(opts \\ [])

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

Runs git rev-parse to resolve refs and query repository information.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - ref to resolve (e.g., "HEAD", "main")
  • :short - abbreviate SHA (--short, or integer for length)
  • :verify - verify ref exists (--verify)
  • :show_toplevel - show repository root (--show-toplevel)
  • :is_inside_work_tree - check if inside worktree (--is-inside-work-tree)
  • :is_inside_git_dir - check if inside .git dir (--is-inside-git-dir)
  • :is_bare_repository - check if bare repo (--is-bare-repository)
  • :git_dir - show .git directory (--git-dir)
  • :abbrev_ref - symbolic ref name (--abbrev-ref)
  • :symbolic_full_name - full symbolic name (--symbolic-full-name)
  • :show_cdup - show path to root (--show-cdup)
  • :show_prefix - show path from root (--show-prefix)
  • :absolute_git_dir - absolute .git path (--absolute-git-dir)
  • :git_common_dir - common git dir (--git-common-dir)

Examples

Git.rev_parse(ref: "HEAD")
Git.rev_parse(show_toplevel: true)
Git.rev_parse(abbrev_ref: true, ref: "HEAD")

revert(opts \\ [])

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

Runs git revert to create a commit that undoes a previous commit.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :commits - list of commit refs to revert
  • :no_commit - revert without committing (--no-commit)
  • :abort - abort in-progress revert (--abort)
  • :continue_revert - continue after conflict resolution (--continue)
  • :skip - skip current commit (--skip)
  • :mainline - parent number for merge commits (-m)
  • :signoff - add Signed-off-by (--signoff)
  • :no_edit - use default commit message (--no-edit)
  • :strategy - merge strategy (--strategy)
  • :strategy_option - strategy option (--strategy-option)

Examples

Git.revert(commits: ["abc1234"])
Git.revert(commits: ["abc1234"], no_commit: true)
Git.revert(abort: true)

rm(opts \\ [])

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

Runs git rm to remove files from the working tree and index.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :files - list of files to remove (required)
  • :cached - only remove from index (--cached)
  • :force - force removal (-f)
  • :recursive - recursive removal (-r)
  • :dry_run - dry run (-n)
  • :quiet - suppress output (-q)

Examples

Git.rm(files: ["old_file.ex"])
Git.rm(files: ["lib/"], recursive: true, cached: true)

shortlog(opts \\ [])

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

Runs git shortlog to summarize log output by author.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :numbered - sort by number of commits (-n)
  • :summary - suppress commit descriptions, show count only (-s)
  • :email - show email addresses (-e)
  • :group - group by field (--group=, e.g. "author", "committer")
  • :ref - ref range (e.g. "v1.0..HEAD")
  • :max_count - limit number of commits (--max-count=N)
  • :since - show commits after date (--since=)
  • :until_date - show commits before date (--until=)
  • :all - all branches (--all)

Examples

Git.shortlog(summary: true, numbered: true)
Git.shortlog(email: true, ref: "v1.0..HEAD")

show(opts \\ [])

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

Runs git show to display information about a git object.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - the object to show (default: "HEAD")
  • :format - custom format string (--format)
  • :stat - show diffstat (--stat)
  • :name_only - show only file names (--name-only)
  • :name_status - show file names and status (--name-status)
  • :no_patch - suppress diff output (--no-patch)
  • :abbrev_commit - abbreviate commit hash (--abbrev-commit)
  • :oneline - one-line format (--oneline)
  • :diff_filter - filter diffs (--diff-filter)
  • :quiet - suppress output (--quiet)

Examples

Git.show()
Git.show(ref: "HEAD~1", stat: true)
Git.show(ref: "v1.0.0", no_patch: true)

show_ref(opts \\ [])

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

Runs git show-ref to list references in the local repository.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :heads - only show heads (--heads)
  • :tags - only show tags (--tags)
  • :verify - verify a specific ref exists (--verify)
  • :hash - show only the SHA (--hash), or an integer for abbreviated hash
  • :abbrev - abbreviate object names to N digits (--abbrev=N)
  • :dereference - dereference tags (-d)
  • :quiet - suppress output, useful with :verify (-q)
  • :exclude_existing - filter out existing refs (--exclude-existing)
  • :patterns - list of ref patterns to match

Examples

Git.show_ref()
Git.show_ref(heads: true)
Git.show_ref(tags: true)
Git.show_ref(verify: true, patterns: ["refs/heads/main"])
Git.show_ref(verify: true, quiet: true, patterns: ["refs/heads/main"])

sparse_checkout(opts \\ [])

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

Runs git sparse-checkout to manage sparse-checkout patterns.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :init - initialize sparse-checkout
  • :set - list of patterns to set
  • :add - list of patterns to add
  • :list - list current patterns (default true)
  • :disable - disable sparse-checkout
  • :reapply - reapply current sparse-checkout rules
  • :check_rules - check sparse-checkout rules
  • :cone - use cone mode (--cone)
  • :no_cone - use non-cone mode (--no-cone)
  • :sparse_index - use sparse index (--sparse-index)
  • :no_sparse_index - do not use sparse index (--no-sparse-index)

Examples

Git.sparse_checkout()
Git.sparse_checkout(init: true, cone: true)
Git.sparse_checkout(set: ["src/", "docs/"])
Git.sparse_checkout(disable: true)

stash(opts \\ [])

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

Runs git stash to list, save, pop, apply, drop, clear, branch, or show stash entries.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :save - push current changes onto the stash (default false)
  • :pop - pop the top stash entry (default false)
  • :apply - apply a stash entry without dropping it (default false)
  • :drop - drop a stash entry (default false)
  • :clear - remove all stash entries (default false)
  • :branch - create a branch with the given name from a stash entry
  • :show - show the diff for a stash entry (default false); returns {:ok, stdout} with the raw diff
  • :message - message for the stash entry (used with :save)
  • :index - stash index for :pop, :apply, :drop, :branch, or :show (e.g., 0 for stash@{0})
  • :include_untracked - include untracked files when saving (default false)
  • :keep_index - keep staged changes in the index when saving (--keep-index, default false)

status(opts \\ [])

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

Runs git status and returns the parsed output.

The output always uses --porcelain=v1 -b so the parser keeps working. The options below add flags on top of that base.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :untracked_files - :no, :normal, or :all to control how untracked files are reported (--untracked-files=<mode>, default nil)
  • :ignored - include ignored files (--ignored, default false)
  • :ignore_submodules - when to ignore submodule changes, e.g. "all" (--ignore-submodules=<when>, default nil)
  • :renames - detect renames (--renames, default false)
  • :no_renames - disable rename detection (--no-renames, default false)
  • :pathspec - a list of paths to limit the status to, appended after a -- separator (default [])
  • All other options are passed to the underlying command.

submodule(opts \\ [])

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

Runs git submodule to manage submodules.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :status - show submodule status (default true)
  • :init - initialize submodules
  • :update - update submodules
  • :add_url - URL to add as submodule
  • :add_path - path for new submodule
  • :deinit - path to deinit
  • :sync - sync URLs
  • :summary - show summary of changes
  • :set_branch - set branch for submodule (requires :path)
  • :set_url - set URL for submodule (requires :path)
  • :path - submodule path for set-branch/set-url/init/update
  • :recursive - apply recursively (--recursive)
  • :force - force operation (--force)
  • :remote - use remote tracking branch (--remote)
  • :merge - merge into working tree (--merge)
  • :rebase - rebase onto new commits (--rebase)
  • :depth - shallow clone depth (--depth)
  • :reference - reference repository (--reference)
  • :name - logical name for add (--name)
  • :branch - branch for add (-b)
  • :quiet - suppress output (-q)
  • :all - all submodules for deinit (--all)

The foreach subcommand is not supported because it requires an arbitrary shell command, which does not fit the structured command model.

Examples

Git.submodule()
Git.submodule(add_url: "https://example.com/lib.git", add_path: "vendor/lib")
Git.submodule(init: true)
Git.submodule(update: true, recursive: true)
Git.submodule(deinit: "vendor/lib", force: true)

switch(opts \\ [])

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

Runs git switch to change branches.

git switch is the modern (Git 2.23+) replacement for the branch-switching role of git checkout. It is more focused and prevents accidental file operations.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :branch - branch name to switch to
  • :create - create a new branch and switch to it (-c)
  • :force_create - create or reset a branch and switch to it (-C)
  • :start_point - commit/ref to create the branch from when using :create/:force_create (default nil)
  • :detach - switch to a commit in detached HEAD state (--detach)
  • :force - force switch even with uncommitted changes (--force)
  • :discard_changes - discard local changes (--discard-changes)
  • :merge - merge local changes into new branch (--merge)
  • :orphan - create a new orphan branch (--orphan)
  • :guess - enable/disable branch name guessing from remotes (--guess/--no-guess)
  • :track - set upstream tracking branch (--track)

Examples

Git.switch(branch: "main")
Git.switch(branch: "feat/new", create: true)
Git.switch(branch: "v1.0.0", detach: true)

symbolic_ref(opts \\ [])

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

Runs git symbolic-ref to read, create, or delete symbolic refs.

A symbolic ref is a ref that points to another ref (e.g., HEAD typically points to a branch ref).

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - the symbolic ref to read/write (e.g., "HEAD")
  • :target - if set, writes the symbolic ref to point to this target
  • :short - shorten the ref name (--short)
  • :delete - delete the symbolic ref (--delete)
  • :quiet - suppress error messages (--quiet)

Examples

Git.symbolic_ref(ref: "HEAD")
Git.symbolic_ref(ref: "HEAD", short: true)
Git.symbolic_ref(ref: "HEAD", target: "refs/heads/main")

tag(opts \\ [])

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

Runs git tag to list, create, or delete tags.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :create - name of a new tag to create
  • :message - annotation message (creates an annotated tag when set with :create)
  • :file - read the annotation message from this file (-F <path>, annotated); takes precedence over :message and never opens an editor
  • :sign - GPG-sign the annotated tag with the default key (-s); requires :message or :file so no editor opens (default false)
  • :local_user - GPG-sign the annotated tag with the given key (-u <keyid>); takes precedence over :sign and requires :message or :file (default nil)
  • :force - replace an existing tag on creation (-f, moves the tag)
  • :delete - name of a tag to delete
  • :ref - commit ref to tag (default: HEAD)
  • :sort - sort order for listing (e.g., "-version:refname")
  • :contains - list only tags that contain this commit (--contains <commit>)
  • :points_at - list only tags that point at this object (--points-at <object>)
  • :list_glob - list only tags matching this glob (--list <glob>)

update_index(opts \\ [])

@spec update_index(keyword()) :: {:ok, :done} | {:error, term()}

Runs git update-index to populate or modify the index directly.

Plumbing command. :cacheinfo inserts index entries with no working-tree file (assemble arbitrary trees with write_tree); :assume_unchanged and :skip_worktree hide local changes to tracked files.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :cacheinfo - list of {mode, object, path} tuples (--cacheinfo)
  • :add / :remove / :refresh - the corresponding flags (default false)
  • :chmod - "+x" or "-x" (--chmod, default nil)
  • :assume_unchanged / :skip_worktree - set the corresponding bits
  • :index_info - read the bulk index-info format from :stdin (requires the forcola runner)
  • :stdin - the --index-info payload
  • :files - pathspec

Examples

Git.update_index(cacheinfo: [{"100644", blob_sha, "config.json"}])
Git.update_index(skip_worktree: true, files: ["local.env"])

update_ref(opts \\ [])

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

Runs git update-ref to update the object name stored in a ref.

Supports conditional updates (compare-and-swap), reflog messages, and deletion of refs.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :ref - the ref to update
  • :new_value - new value for the ref
  • :old_value - expected current value (for CAS)
  • :delete - delete the ref (-d)
  • :create_reflog - create a reflog entry (--create-reflog)
  • :message - reflog message (-m)
  • :no_deref - don't dereference symbolic refs (--no-deref)

Examples

Git.update_ref(ref: "refs/heads/main", new_value: "abc123")
Git.update_ref(ref: "refs/heads/old", delete: true)

var(opts \\ [])

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

Runs git var to read git's logical variables.

With no :name, runs git var -l and returns a map of every variable to its value. With :name, looks up a single variable and returns its value string.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :name - a single variable to look up (e.g., "GIT_EDITOR")

Examples

{:ok, vars} = Git.var()
vars["init.defaultbranch"] #=> "main"

{:ok, editor} = Git.var(name: "GIT_EDITOR")

verify_commit(commit, opts \\ [])

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

Runs git verify-commit to check the GPG signature of a commit.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :verbose - print the contents of the commit object before verifying (-v)
  • :raw - print the raw gpg status output (--raw)

Examples

Git.verify_commit("HEAD")
Git.verify_commit("abc123", verbose: true)

verify_tag(tag, opts \\ [])

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

Runs git verify-tag to check the GPG signature of a tag.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :verbose - print the contents of the tag object before verifying (-v)
  • :raw - print the raw gpg status output (--raw)
  • :format - format string for output (--format=)

Examples

Git.verify_tag("v1.0")
Git.verify_tag("v1.0", verbose: true)

version(opts \\ [])

@spec version(keyword()) :: {:ok, Git.Version.t()} | {:error, term()}

Runs git --version and returns a parsed Git.Version struct.

Useful for gating behavior on the installed git version.

Options

  • :config - a Git.Config struct (default: Git.Config.new())

Examples

{:ok, v} = Git.version()
v.major #=> 2
v.raw   #=> "git version 2.50.1 (Apple Git-155)"

worktree(opts \\ [])

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

Runs git worktree to manage linked working trees.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :list - list worktrees (default true)
  • :add_path - path for new worktree
  • :add_branch - existing branch for new worktree
  • :add_new_branch - create new branch with -b
  • :remove_path - worktree path to remove
  • :prune - prune stale worktree info
  • :force - force operation (-f)
  • :detach - detach HEAD (--detach)
  • :lock - lock new worktree (--lock)

Examples

Git.worktree()
Git.worktree(add_path: "/tmp/feature", add_new_branch: "feat/new")
Git.worktree(remove_path: "/tmp/feature", force: true)

write_tree(opts \\ [])

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

Runs git write-tree to record the current index as a tree object.

Plumbing command. Writes a tree object from the current index (the staged content) and returns its SHA. This is the counterpart to commit_tree/1: write-tree produces the tree SHA that commit-tree needs, so together they build a commit without touching HEAD or the working tree.

Options

  • :config - a Git.Config struct (default: Git.Config.new())
  • :prefix - write the tree for this subdirectory of the index (--prefix)
  • :missing_ok - allow objects that are not in the object database (--missing-ok, default false)

Examples

{:ok, tree} = Git.write_tree()
{:ok, tree} = Git.write_tree(prefix: "lib")