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 --helpflags 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
-Chandling: Every command supports.repo_path()for repository context. - Command unifying traits: Traits like
RepoPathunify 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().await?;
// git -C /path/to/repo status --porcelain
let output = status::new()
.repo_path(Path::new("/path/to/repo"))
.porcelain()
.build()
.capture_stdout()
.string().await?;
// 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().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
.capture_stdout() // Returns cmd_proc::Capture
.string().await?;
// Capture full output (stdout + stderr)
let output = git_proc::show::new("HEAD:path/to/file")
.build()
.output().await?;
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
| Module | Command | Description |
|---|---|---|
add | git add | Add file contents to the index |
clone | git clone | Clone a repository |
commit | git commit | Record changes to the repository |
config | git config | Get and set repository options |
fetch | git fetch | Download objects and refs |
init | git init | Create an empty repository |
ls_remote | git ls-remote | List references in a remote |
push | git push | Update remote refs |
remote | git remote | Manage remotes (get-url) |
rev_list | git rev-list | List commit objects |
rev_parse | git rev-parse | Parse revision specifications |
show | git show | Show objects |
show_ref | git show-ref | List references |
status | git status | Show working tree status |
url | - | URL and remote types (GitUrl, Remote, RemoteName) |
worktree | git worktree | Manage 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