A fast, modern Rust tool that provides concise git repository status information. Perfect for shell prompts, scripts, and large repositories/monorepos.
- Fast: Pure Rust implementation using
gix
(Gitoxide) - Concise: Shows branch, upstream, and change summary in minimal format
- Modern: Built with modern Rust patterns and best practices
- Safe: Proper error handling and memory safety
- Configurable: CLI options for different use cases
git clone https://github.com/stephenyu/gitstatus.git
cd gitstatus
cargo install --path .
If published to crates.io:
cargo install gitstatus
# In any git repository
gitstatus
# Output: main origin/main ✓
# With changes
gitstatus
# Output: main origin/main +2~1-1
# Show help
gitstatus --help
# Specify a different repository path (also accepts a positional path)
gitstatus --path /path/to/repo
gitstatus /path/to/repo
# Show verbose error messages
gitstatus --verbose
# Show version
gitstatus --version
# Control untracked scanning (default: no)
gitstatus -u no|normal|all # --all is equivalent to -u all
# Skip staged-change counting
gitstatus --no-staged # or -S
# Read branch/upstream directly from .git (lower overhead, less robust)
gitstatus --direct-upstream # or -U
The output consists of three parts separated by spaces:
- Current Branch: Name of the current branch (or "HEAD" if detached)
- Upstream Branch: Name of the upstream branch (if configured and different from current)
- Changes Summary: Summary of repository changes
✓
- Clean working directory^N
- N staged changes (index differs fromHEAD^{tree}
)~N
- N renames/copies between index and worktree~N
- N modified/type-changed/conflict entries between index and worktree-N
- N deleted files (index vs worktree)+N
- N untracked files
Notes:
- The
~
symbol can appear twice: once for renames/copies and once for other modifications. - Additions that are staged are counted in
^N
; before staging, they appear as untracked+N
.
# Clean repository on main branch tracking origin/main
$ gitstatus
main origin/main ✓
# Repository with staged, renamed, modified, deleted and untracked changes
$ gitstatus
main origin/main ^1~2~3-1+4
# Detached HEAD state
$ gitstatus
HEAD ✓
# Branch without upstream
$ gitstatus
feature-branch ✓
This version represents a complete modernization of the codebase:
- Better Error Handling: Uses
anyhow
for context-rich error messages - Lightweight CLI: Manual argument parsing for zero additional dependencies
- Type Safety: Structured data types instead of string manipulation
- Memory Safety: No more potential panics from string indexing
- Separation of Concerns: Clear separation between data collection, processing, and output
- Pure
gix
: Eliminated externalgit
command calls in favor ofgix
(Gitoxide) - Structured Status: Uses
gix::status
platform andtree_index_status()
for precise, fast diffs - Extensible Design: Easy to add new features and status indicators
- Fast default: Avoid scanning untracked files by default (equivalent to
git -uno
) - Parallel checks: Uses
gix
parallel feature to check tracked-file modifications efficiently - Minimal I/O: No process spawning; tracked-only checks for prompt use are extremely fast
- New flags:
--no-staged
(-S
): skip staged-change counting when you want minimal status--direct-upstream
(-U
): read branch/upstream directly from.git
for lowest overhead (may miss config layering/worktrees)
- Proper Error Propagation: No more silent failures with
process::exit(1)
- Graceful Handling: Better handling of edge cases (detached HEAD, no upstream, etc.)
- Input Validation: Validates repository paths and handles invalid UTF-8
- Clear Output: Compact summary with consistent symbols (
^
,~
,-
,+
,✓
) - Verbose Mode: Optional detailed error messages for debugging
- Flexible Paths: Can check status of any repository, not just current directory
- Help/Version: Built-in usage and
--version
By default, gitstatus
is optimized for shell prompts and large repos:
- It compares
HEAD^{tree}
to the index for staged changes usingRepository::tree_index_status()
. - It compares the index to the working tree using
Repository::status(...).into_index_worktree_iter(...)
with untracked disabled unless requested. - Untracked mode mapping:
- default /
-u no
: no untracked scan (no dirwalk) -u normal
: collapsed untracked-u all
or--all
: full untracked listing
- default /
Additional flags affecting performance:
--no-staged
(-S
): disables staged diff computation (HEAD^{tree}
vs index)--direct-upstream
(-U
): avoids full config resolution by reading.git/HEAD
and.git/config
directly (less accurate in complex setups)- Submodule checks and rename tracking are disabled by default for speed; they can be enabled later if needed.
# Build
cargo build
# Run tests
cargo test
# Run with development features
cargo run -- --verbose
# Check formatting and lints
cargo fmt --check
cargo clippy
- Rust 1.70+ (specified in Cargo.toml)
- Git repository to analyze
GPL-3.0-only
Contributions are welcome! Please feel free to submit a Pull Request.