All four states detect correctly:
ahead→ pending commit (commit not yet pushed)dirty→ local changes, no upstreamupToDate→ clean
What I built
git-recursive at /home/david/projects/code-associates/utilities/git-recursive/git-recursive (executable), styled to match the sibling git-identity utility.
Usage: git-recursive status [parent-dir] — defaults to the current directory if no parent is given.
It recursively descends from the parent directory, and for each cloned repo it finds (a directory with a .git entry) it reports one or more states, then stops descending into that repo:
| State | Meaning |
|---|---|
local changes |
working tree is dirty (staged/modified/untracked) |
pending commit |
commits exist locally but aren't pushed upstream |
no upstream |
branch has commits but no upstream to push to |
clean |
nothing outstanding |
Notes on a couple of judgment calls:
- I split your "needs pushing" concern into two distinct states — uncommitted work (
local changes) vs. committed-but-unpushed (pending commit) — since a repo can be in either or both, and they call for different actions (commit vs. push). A repo with both showslocal changes, pending commit. - I added
no upstreambecause a freshly-cloned-but-never-pushed branch otherwise looks clean even though it has unpushed work. In your scenario (config repos cloned from remotes) most repos will have an upstream, so this mainly flags anomalies. - Clean repos are listed too, so you get a full inventory of what was scanned rather than silence. Easy to filter to only-interesting repos later if you'd prefer — just say the word.
The subcommand dispatch is in place, so adding pull, push, etc. later is a matter of dropping in another cmd_* function. Want me to add a README.md to match git-identity, or wire up any further subcommands?