git-for-each-repo
Run Git commands across multiple repositories
TLDR
Run maintenance on each of a list of repositories stored in the maintenance.repo user configuration variable
Run git pull on each repository listed in a global configuration variable
SYNOPSIS
git for-each-repo [options...] <command> [args...]
PARAMETERS
--config=<name>=<value>
Set temporary Git config key to value for each repository during command execution. Repeatable.
-h, --help
Display usage help and exit.
-V, --version
Output version information and exit.
DESCRIPTION
The git-for-each-repo command is a Perl script from Git's contrib directory that discovers all Git repositories under the current directory tree and executes a specified command in each one.
It recursively searches for directories containing a .git subdirectory, verifies they are valid Git repositories using git rev-parse --git-dir, and changes into each repository's root directory before running the provided command with its arguments.
This is useful for batch operations like updating submodules, running git fetch, git status, or custom maintenance scripts across multiple local repos without manual navigation.
Temporary Git configurations can be set via --config options, applied only during execution in each repo. It handles errors gracefully, printing repo paths and exit statuses for failed commands, and supports piping output.
Ideal for developers managing monorepos or directory structures with scattered Git projects.
CAVEATS
Only processes repositories with a working tree (skips bare repos unless .git is in expected place); changes directory context, so commands must be directory-agnostic or handle it; no built-in parallelism; reports but continues on errors.
EXAMPLES
git for-each-repo git fetch
Fetch updates in all repos.
git for-each-repo --config=user.email=bot@example.com git commit -m 'Update'
Commit with temp config.
EXIT STATUS
0 if all commands succeed, non-zero if any repo command fails (but script continues).
HISTORY
Introduced in Git contrib/for-each-repo around 2012 (Git 1.7.x era), maintained as a utility script. Evolved with minor fixes for edge cases like nested repos.


