Skip to main content

Crate git_proc

Crate git_proc 

Source
Expand description

§git-proc

Async process-based git CLI wrapper with builder API, built on cmd-proc.

§Why

Shelling out to git is often the right choice: it’s battle-tested, handles edge cases, and matches what users run manually. But raw Command::new("git") calls scatter string arguments throughout your codebase, making them hard to review, refactor, and test.

git-proc provides:

  • Discoverable API: Method names match git --help flags exactly. IDE autocomplete guides you.
  • Compile-time structure: Builders ensure required arguments are present and ordered correctly.
  • Testable commands: Compare built commands without executing them using test_eq().
  • Consistent -C handling: Every command supports .repo_path() for repository context.
  • Command unifying traits: Traits like RepoPath unify common options across all command builders, ensuring a consistent interface regardless of the specific git command. More unifying traits will be added as this library evolves.

This is not a reimplementation of git. It shells out to the git binary. For embedded git functionality, use gitoxide or git2.

§Coverage

Command and flag coverage is not exhaustive. Only what was needed by direct dependencies in the mbj/mrs workspace has been implemented. Similar crates exist (e.g., git-cmd), but it was cheaper to centralize a minimal library here than to upstream all missing fields to external projects.

§Usage

Each git command has a corresponding builder struct in its own module. Builders use method names matching the git CLI options from git <command> --help.

use git_proc::{Build, rev_parse, status, clone, fetch, worktree};
use git_proc::repository;
use std::path::Path;

// git rev-parse --abbrev-ref HEAD
let branch = rev_parse::new()
    .abbrev_ref()
    .rev("HEAD")
    .build()
    .stdout_capture()
    .string().await?;

// git -C /path/to/repo status --porcelain
let output = status::new()
    .repo_path(Path::new("/path/to/repo"))
    .porcelain()
    .build()
    .stdout_capture()
    .string().await?;

// git clone --bare <address> <path>
let address: repository::Address = "https://github.com/user/repo.git".parse()?;
clone::new(&address)
    .bare()
    .directory(Path::new("/path/to/bare.git"))
    .status().await?;

// git -C /path/to/repo fetch --all
fetch::new()
    .repo_path(Path::new("/path/to/repo"))
    .all()
    .status().await?;

// git -C /path/to/repo worktree add -b new-branch /path/to/worktree origin/main
worktree::add(Path::new("/path/to/worktree"))
    .repo_path(Path::new("/path/to/repo"))
    .new_branch("new-branch")
    .commit_ish("origin/main")
    .status().await?;

§Stream Handling

git-proc builders focus on command construction. For stream capture, use the Build trait to get a cmd_proc::Command, then use its stream methods:

use git_proc::Build;

// Capture stdout
let sha = git_proc::rev_parse::new()
    .rev("HEAD")
    .build()                  // Returns cmd_proc::Command
    .stdout_capture()         // Returns cmd_proc::CaptureSingle<Stdout>
    .string().await?;

// Capture both stdout and stderr
let result = git_proc::show::new("HEAD:path/to/file")
    .build()
    .stdout_capture()
    .stderr_capture()
    .accept_nonzero_exit()
    .run().await?;

if result.status.success() {
    let content = String::from_utf8(result.stdout)?;
}

This design keeps git-proc focused on git command building while delegating all stream configuration to cmd_proc::Command.

§Available Commands

ModuleCommandDescription
addgit addAdd file contents to the index
clonegit cloneClone a repository
commitgit commitRecord changes to the repository
configgit configGet and set repository options
fetchgit fetchDownload objects and refs
initgit initCreate an empty repository
ls_remotegit ls-remoteList references in a remote
pushgit pushUpdate remote refs
remotegit remoteManage remotes (get-url)
rev_listgit rev-listList commit objects
rev_parsegit rev-parseParse revision specifications
showgit showShow objects
show_refgit show-refList references
statusgit statusShow working tree status
repository-Repository address and remote types (Address, Remote, RemoteName)
worktreegit worktreeManage worktrees (list, add, remove)

§Testing

Enable the test-utils feature to access the test_eq() method on builders, which compares the built command against an expected cmd_proc::Command using debug representation.

#[cfg(feature = "test-utils")]
#[test]
fn test_fetch_all() {
    use std::path::Path;

    let expected = cmd_proc::Command::new("git")
        .argument("-C")
        .argument("/repo")
        .argument("fetch")
        .argument("--all");

    git_proc::fetch::new()
        .repo_path(Path::new("/repo"))
        .all()
        .test_eq(&expected);
}

Modules§

add
branch
Git branch name type with validation.
checkout
git checkout command builder using a typestate to enforce that a target is chosen before the command can be executed.
clean
clone
commit
commit_id
Git commit object ID type with validation.
commit_ish
Commit-ish target type and reusable typestate markers shared by command builders that take a “thing that names a tree state” — git checkout, git reset, etc.
config
diff
fetch
init
ls_remote
push
ref_format
Shared validation for git reference names.
remote
repository
reset
git reset command builder.
rev_list
rev_parse
show
show_ref
status
tag
Git tag name type with validation, plus git tag command builders.
worktree

Enums§

CommandError

Traits§

Build
Trait for building a command without executing it.
Porcelain
Trait for git command builders that support porcelain output.
RepoPath
Trait for git command builders that support a repository path.