Skip to main content

Crate git_proc

Crate git_proc 

Source
Expand description

§git-proc

Process-based git CLI wrapper with builder API.

§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::url::GitUrl;
use std::path::Path;

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

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

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

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

// 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()?;

§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
    .capture_stdout()         // Returns cmd_proc::Capture
    .string()?;

// Capture full output (stdout + stderr)
let output = git_proc::show::new("HEAD:path/to/file")
    .build()
    .output()?;

if output.success() {
    let content = output.into_stdout_string()?;
}

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
url-URL and remote types (GitUrl, 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.
clone
commit
config
fetch
init
ls_remote
push
remote
rev_list
rev_parse
show
show_ref
status
url
worktree

Structs§

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.