- Go 84.2%
- Shell 15.8%
|
|
||
|---|---|---|
| .gitea/workflows | ||
| .gitignore | ||
| build.sh | ||
| complete.go | ||
| ensure_go.sh | ||
| git.go | ||
| go.mod | ||
| gp.go | ||
| install.sh | ||
| main.go | ||
| publish.sh | ||
| README.md | ||
| report.go | ||
| scan.go | ||
| setup_script.sh | ||
| test.sh | ||
| whatsdirty_test.go | ||
whatsdirty
Simple tool to ease committing and pushing code changes across lots of repos.
Scans every git repository under a directory, fetches them (throttled per server), rebases the ones that are behind, and reports what is dirty, unpushed or stuck. Anything worth pushing is handed to gp, which commits, pushes and waits for CI.
whatsdirty <directory> # scan, then hand dirty/unpushed repos to `gp -y`
whatsdirty -a <directory> # ask before including each repo
wd # shortcut for `whatsdirty -y`
The directory is remembered in ~/.config/whatsdirty.conf, so later runs need
no argument.
| Variable | Default | Effect |
|---|---|---|
WHATSDIRTY_MAX_PER_SERVER |
8 | Concurrent fetches against any one host. Different servers are fetched in parallel. |
WHATSDIRTY_SKIP_DIRS |
node_modules,vendor,target,.venv,__pycache__ |
Directories not descended into when looking for repos. Set it empty to scan everything. |
WHATSDIRTY_SSH_MULTIPLEX |
on | Share one ssh connection per host across all fetches. Set to 0 to disable. Ignored if you set your own GIT_SSH_COMMAND. |
Connection sharing is where most of the scan time went: against a forge across
the internet, the ssh handshake costs several times the git work it wraps. Note
that sshd's MaxSessions (default 10) caps how many fetches can share one
connection — which is why WHATSDIRTY_MAX_PER_SERVER defaults to 8. Raising it
past that needs MaxSessions raised on the server, or multiplexing turned off;
otherwise the server starts refusing sessions. A fetch that fails is retried
once on its own connection, so a refusal recovers by itself.
Anything under a _deps directory is always skipped: build trees vendor whole
checkouts there.
Ctrl-C cancels immediately, killing every in-flight git. If it interrupts a
rebase, it names the repos left mid-flight — git rebase --abort restores them.
Building
Go, no dependencies outside the standard library.
./build.sh # -> output/whatsdirty
./test.sh # vet, unit tests, and CLI checks against a sandbox
./publish.sh # cross-build and publish linux+macos / amd64+arm64
test.sh runs against a throwaway HOME and repositories it creates itself.
Don't point a scan at a directory you care about while testing: a real run saves
over your saved directory and ends by committing and pushing every dirty repo it
finds.