lsgit is a command-line tool that works like ls — but for git repositories. Point it at any directory and it instantly shows you every git repo it finds, along with the current branch, working-tree status, and how far ahead or behind the remote tracking branch you are.
/Users/you/workspace
my-api main ✓ clean
frontend feature/dark-mode ● 3 changes ↑2
infra main ● 1 change
old-service HEAD:3f9a12c ● 7 changes ↓14
docs main ✓ clean
5 repos 2 clean 3 dirty
- Features
- Installation
- Usage
- Parameters & Flags
- Output Reference
- Contributing
- Troubleshooting
- License
- Scans subdirectories and identifies git repositories
- Shows current branch name (or short SHA for detached HEAD)
- Shows working-tree status: clean or number of changed/staged/untracked files
- Shows ahead/behind count relative to the upstream tracking branch
- Parallel execution — all
gitcalls run concurrently for speed - Recursive scanning with configurable depth
- Colorized output (auto-disabled when piped)
- Optional
git fetchbefore status check (-f) - Zero runtime dependencies — single static binary
brew install itinance/tap/lsgitTo update:
brew upgrade lsgitDownload the latest .deb package from the Releases page:
curl -sLO https://github.com/itinance/lsgit/releases/latest/download/lsgit_linux_amd64.deb
sudo dpkg -i lsgit_linux_amd64.debFor ARM64 (e.g. Raspberry Pi, AWS Graviton):
curl -sLO https://github.com/itinance/lsgit/releases/latest/download/lsgit_linux_arm64.deb
sudo dpkg -i lsgit_linux_arm64.debRPM-based distros (Fedora, RHEL, CentOS):
sudo rpm -i https://github.com/itinance/lsgit/releases/latest/download/lsgit_linux_amd64.rpmRequires Go 1.21 or later.
git clone https://github.com/itinance/lsgit.git
cd lsgit
make build
make install # copies binary to /usr/local/binOr without make:
go build -o lsgit .
sudo mv lsgit /usr/local/bin/# Scan the current directory (one level deep)
lsgit
# Scan a specific directory
lsgit ~/workspace
# Also show non-git directories
lsgit -a ~/workspace
# Recurse up to 3 levels deep to find nested repos
lsgit -d 3 ~/workspace
# Recurse with no depth limit
lsgit -d 0 ~/workspace
# Fetch from remote before checking status
lsgit -f ~/workspace
# Combine flags
lsgit -a -d 2 -f ~/workspace
# Show remote origin URL for each repository
lsgit -u ~/workspace
# Disable color (useful for scripts and logging)
lsgit --no-color ~/workspace | tee repos.txt| Flag | Short | Default | Description |
|---|---|---|---|
--all |
-a |
false |
Show non-git directories too (displayed as —) |
--depth |
-d |
1 |
Max depth for recursive scanning. 0 means unlimited. |
--fetch |
-f |
false |
Run git fetch before checking status. Makes results accurate against remote but is slower. |
--url |
-u |
false |
Show the remote origin URL below each repository name. |
--no-color |
false |
Disable ANSI color output. Automatically active when stdout is not a terminal. | |
--version |
-v |
Print version and exit. | |
--help |
-h |
Show help. |
By default (-d 1) lsgit only looks at direct subdirectories of the target path. Increase depth to find repos nested inside non-repo directories:
workspace/ ← target
├── my-api/ ← found at depth 1 (repo)
├── clients/ ← not a repo, recurse if depth > 1
│ ├── client-a/ ← found at depth 2
│ └── client-b/ ← found at depth 2
└── tools/ ← not a repo, recurse if depth > 1
└── linter/ ← found at depth 2
frontend feature/dark-mode ● 3 changes ↑2 ↓1
^ ^ ^ ^
| | | |
repo name branch name status ahead/behind
| Symbol | Meaning |
|---|---|
✓ clean |
Working tree is clean, nothing to commit |
● N changes |
N files are modified, staged, or untracked |
! error |
git returned an error (repo may be corrupt or inaccessible) |
| Value | Meaning |
|---|---|
main / feature/x |
Normal branch name |
HEAD:3f9a12c |
Detached HEAD state — shows short SHA |
(unknown) |
Could not determine branch or SHA |
| Symbol | Meaning |
|---|---|
↑N |
N commits ahead of the remote tracking branch (unpushed) |
↓N |
N commits behind the remote tracking branch (need to pull) |
↑N ↓M |
Diverged from remote |
Ahead/behind is only shown when a remote tracking branch is configured. Repos with no remote or no tracking branch show nothing here.
Contributions are welcome. Please open an issue first for significant changes so we can discuss the approach.
git clone https://github.com/itinance/lsgit.git
cd lsgit
go mod tidy
make buildmake test
# or
go test ./...To test the full GoReleaser pipeline without publishing:
# Install goreleaser if needed
brew install goreleaser
make snapshot
# Artifacts will appear in dist/Maintainers with the required tokens:
git tag v1.2.3
make releaseThis requires two environment variables:
GITHUB_TOKEN— a GitHub personal access token withreposcopeHOMEBREW_TAP_TOKEN— a token with write access to theitinance/homebrew-taprepo
| File | Purpose |
|---|---|
main.go |
CLI definition, flags, entry point |
scanner.go |
Directory traversal and git introspection |
display.go |
Colorized tabular output |
version.go |
Version string (overridden by ldflags at build time) |
.goreleaser.yml |
Cross-platform build and release pipeline |
Makefile |
Developer shortcuts |
- Keep the binary dependency-free at runtime (
gitmust be inPATH— that's it) - New flags should have sensible defaults that preserve existing behavior
- Avoid adding dependencies; the current dep count (cobra + fatih/color) is intentional
The binary is not on your PATH. If you installed manually:
# Check where it is
which lsgit || ls /usr/local/bin/lsgit
# Add /usr/local/bin to your PATH if missing
echo 'export PATH="$PATH:/usr/local/bin"' >> ~/.zshrc
source ~/.zshrcCheck the depth. By default only direct subdirectories are scanned:
lsgit -d 3 .If repos are inside hidden directories (.dotfiles/myrepo), they are skipped intentionally. Hidden directories (starting with .) are never scanned.
git returned a non-zero exit code for that repository. Common causes:
# Check manually
git -C /path/to/repo status
# Common issues:
# - Repo is corrupt: git fsck
# - Permissions problem: ls -la /path/to/repo/.git
# - Safe.directory issue: git config --global --add safe.directory /path/to/repoEnsure your terminal supports ANSI colors. If you are piping output, colors are disabled automatically. Force them off with --no-color or check:
echo $TERM # should be xterm-256color or similar
echo $NO_COLOR # if set, color libraries respect itThe repo has no remote tracking branch configured:
# Check
git -C /path/to/repo branch -vv
# Fix: set upstream for the current branch
git -C /path/to/repo branch --set-upstream-to=origin/main-f runs git fetch on every repo sequentially before reporting. For large workspaces with many repos this can take a while. Consider running it only on a subdirectory:
lsgit -f ~/workspace/active-projectsEnsure your Go version is 1.21 or later:
go versionIf you use asdf:
asdf install golang 1.23.5
asdf set golang 1.23.5MIT — see LICENSE.