git-sync-all: Technical details
How git-sync-all is built: modules, execution order, dry-run wrapper, subshell isolation, lock file, file layout, tests and CI.
git-sync-all: Technical details
File layout
git-sync-all/
βββ bin/git-sync-all Entry point
βββ lib/
β βββ core.sh Strict mode, logging, colors, lock, cleanup
β βββ config.sh Defaults, config loading, validation, --init-config
β βββ cli.sh Arguments, help, version, alias
β βββ repo-discovery.sh Repository search, filters, remote check
β βββ git-ops.sh Git operations, dry-run wrapper
β βββ sync.sh Sync flow, prompts, status, summary
β βββ inventory.sh repos.yml, --verify, cleanup, --init-inventory
β βββ issues.sh GitHub issues via gh
βββ config/
β βββ config.conf.example
β βββ repos.yml.example
βββ tests/ Test scripts
βββ Makefile install, uninstall, link, test, lint, format
βββ install.ps1 Windows installer
Execution order
graph TD
A[parse_args] --> B[load_config]
B --> C[apply_cli_overrides]
C --> D[setup_environment: colors, git check, lock]
D --> E{Mode}
E -->|--verify| F[parse_inventory and verify_inventory]
E -->|--issues| G[parse_inventory and show_issues]
E -->|default| H[discover_repos]
H --> I{--status?}
I -->|yes| J[show_status]
I -->|no| K[sync_all]
J --> L[print_summary]
K --> L
L --> M{Failed greater than 0?}
M -->|yes| N[Exit 1]
M -->|no| O[Exit 0]
--help, --version, --init-config, --setup-alias and --init-inventory already end the tool inside parse_args. The lock is acquired before every mode, so also for --status, --verify and --issues.
Modules
| File | Responsibility |
|---|---|
bin/git-sync-all |
Resolves its own path (also through symlinks), sources all libraries and drives main(). |
lib/core.sh |
set -euo pipefail, colors, logging to stderr, cleanup trap, git check, lock file. |
lib/config.sh |
Defaults, loading the config via source, validation, --init-config. |
lib/cli.sh |
parse_args, apply_cli_overrides, help text, --setup-alias. |
lib/repo-discovery.sh |
find search for .git directories, include/exclude filters, remote check. |
lib/git-ops.sh |
All Git calls, conflict detection, aborting rebase and merge, stash. |
lib/sync.sh |
sync_repository, sync_all, prompts, status table, summary. |
lib/inventory.sh |
Inventory parser, verify_inventory, detection and removal of unlisted repositories. |
lib/issues.sh |
show_issues via the GitHub CLI. |
Design decisions
- Subshells: Every function in
git-ops.shdoes itscdinto the repository in a subshell. The working directory of the main process is never changed. - Dry-run wrapper: Write commands go through
git_cmd, which only prints[DRY-RUN] Would: git ...in a dry run. Read commands always run. Becausesync_repositoryruns inside a command substitution per repository and some calls discard stderr, the lines are only visible forgit addandgit commit. - Conflict detection: The tool compares
git status --porcelainwithgit diff --name-only HEAD..<upstream>and reports files that appear in both lists. - Lock file: Contains the PID. At startup
kill -0checks whether the process is alive. A cleanup trap onEXIT,INTandTERMremoves it again.flockis not used. The path is fixed before the check, so a second instance that exits because of the first one also deletes the first instance's lock file. - Config via
source: There is no parser of its own. Shell variables work in the config, but the file is executed. - Output:
--helpand--versionwrite to stdout, all other user output goes to stderr. Only internal intermediate values (per-repository result, statistics strings) travel via stdout. qin prompts:exit 0runs inside the command substitution ofsync_alland only ends that subshell. The repository counts asFailed.
Tests and CI
make test starts tests/run-tests.sh, which runs all tests/test-*.sh files. The tests cover CLI parsing, config, repository discovery, Git operations, conflict handling, the inventory and the Windows installer. make lint runs ShellCheck, make format checks with shfmt -i 4 -ci -bn, and make check runs everything together. The GitHub Actions pipeline runs ShellCheck, shfmt, PSScriptAnalyzer for install.ps1 and the tests on Ubuntu and Windows.