A bash-based tool for managing multiple Git repositories with multi-remote synchronization capabilities. Designed for GitHub workflows with containerized execution support.
Platform Support: Linux/Unix environments only. Tested on various Linux distributions.
- Multi-Remote Support: Sync local repositories with multiple GitHub remotes
- Docker Integration: Containerized execution with automatic dependency management
- YAML Configuration: Centralized configuration with environment variable support
- Configuration Validation: Early validation with descriptive error messages
- Batch Operations: Process multiple repositories simultaneously
- Status Monitoring: Check repository status without making changes
- Flexible Filtering: Target specific repositories using regex patterns
- Automatic Repository Creation: Create GitHub repositories if they don't exist
- Smart Commit Messages: Repository-specific or global commit message configuration
- User ID Mapping: Automatic permission handling in Docker containers
- Set GitHub Description: Quickly update your repository's GitHub description from the command line with
--set-description
. - No Sync Option: Use
--ns
or--no-sync
to perform local operations only, without syncing to remotes.
Prerequisites: Linux/Unix operating system with the following dependencies:
bash
python3
(PyYAML will be automatically installed if needed)git
gh
(GitHub CLI) - Required for repository creationenvsubst
(usually part ofgettext
package)
- Clone this repository to your local machine
- Set up GitHub CLI authentication:
gh auth login
The tool automatically handles Python virtual environments and package installation.
Use Docker for a consistent environment with all dependencies pre-installed:
# Build Docker image locally
docker build -t repos-management-tool .
# Run with all dependencies included
./repos --docker
Note: Pre-built Docker images will be available at
ghcr.io/adamdanielharris/repos
once the first release is published.
See DOCKER.md for complete Docker usage guide.
The config.yaml
file contains detailed documentation and examples. Setup process:
-
Uncomment the template sections at the bottom of
config.yaml
-
Replace placeholder values:
<YOUR_EMAIL>
with your email address<YOUR_GIT_USERNAME>
with your Git username<YOURUSERNAME>
with your GitHub username- Repository names and paths as needed
-
Optionally configure repository-specific commit messages
The tool validates your configuration and provides specific error messages for any unresolved template placeholders.
Example configuration:
# Global Git Configuration
config:
email: "your.email@example.com"
name: "YourGitUsername"
branch: "main"
repos:
my-project:
local: $HOME/git/my-project
commit_message: "Development updates" # Optional: Custom default commit message
remotes:
- https://github.com/yourusername/my-project.git # GitHub URLs required
- https://github.com/yourusername/my-project-backup.git # Backup repository
The tool supports multiple levels of commit message configuration:
-
Repository-specific default (in config.yaml):
repos: my-project: local: $HOME/git/my-project commit_message: "Development updates" # Custom default for this repo remotes: - https://github.com/username/my-project.git
-
Command line override (highest priority):
./repos --gcm "Custom commit message for this run"
-
Global default (when no other message is specified):
- Format:
backup-YYYY-MM-DD
(e.g., "backup-2025-06-10")
- Format:
Priority order: Command line (--gcm
) > Repository default (commit_message
) > Global default (backup-YYYY-MM-DD
)
The configuration supports shell variable expansion using envsubst
. Common variables include:
$HOME
- User's home directory$USER
- Current username$PWD
- Current working directory- Any custom environment variables you define
Examples:
repos:
my-project:
local: $HOME/git/my-project # Expands to /home/username/git/my-project
remotes:
- https://github.com/username/my-project.git
user-app:
local: /home/$USER/projects/app # Expands to /home/username/projects/app
remotes:
- https://github.com/username/user-app.git
custom-project:
local: $PROJECT_ROOT/src # Uses custom environment variable
remotes:
- https://github.com/username/custom-project.git
Environment variables are expanded when the tool runs, allowing for dynamic configuration across different systems.
# Show help and usage information
./repos --help
# Sync all repositories
./repos
# Check status of all repositories without making changes
./repos -s
# Process specific repositories using regex
./repos -r "project.*"
# Force push (use with caution)
./repos -f
# Custom commit message (overrides repository defaults)
./repos --gcm "Feature: Add new functionality"
# Pass specific arguments to git push/pull
./repos --push "--tags" --pull "--rebase"
# Specify path pattern for operations
./repos -p "src/*"
# Run in Docker container (all dependencies included)
./repos --docker
# Run all operations in Docker
./repos --docker
# Status check in Docker
./repos --docker -s
# Docker with custom commit message
./repos --docker --gcm "Docker deployment update"
# Docker with specific repository pattern
./repos --docker -r "web.*"
-f, --force
: Force push to remote repositories--push <args>
: Arguments to pass to git push command--pull <args>
: Arguments to pass to git pull command-r, --repos <regex>
: Specify repositories to process (regex pattern)--gcm <message>
: Git commit message (overrides repository defaults and global default)-p <PathGlob>
: Specify path glob pattern for git operations-s
: Status only mode - show repo status without committing--docker
: Run in Docker container with all dependencies pre-installed--set-description <description>
: Set the GitHub repository description and exit.--ns
,--no-sync
: Do not sync to remote repositories (local operations only).
The tool uses clear visual indicators:
Validating configuration... ✓ PASSED
- Configuration validation successfulValidating configuration... ✗ FAILED
- Configuration validation failed✓ package (imports as 'name') is installed
- Python package status- Colored output for git operations (green for success, red for errors)
First-time setup:
# 1. Edit config.yaml with your details
vim config.yaml
# 2. Test your configuration
./repos -s
# 3. Run full sync
./repos
Daily usage:
# Quick status check
./repos -s
# Sync specific repositories
./repos -r "important.*"
# Force update with custom message
./repos -f --gcm "Emergency backup"
Troubleshooting:
# Test configuration only
./repos --help
# Check what would be processed
./repos -s -r "pattern.*"
When you run the repos
script, it performs the following operations on each configured repository:
- Directory Creation: Creates local repository directory if it doesn't exist
- Repository Initialization:
- If
.git
doesn't exist and directory is empty: Clones from first remote - If
.git
doesn't exist and directory has files: Initializes git repository with main branch
- If
- GitHub Repository Creation: Creates remote GitHub repositories if they don't exist (requires
gh
CLI) - Safe Directory Configuration: Adds repository to git safe directories
-
File Staging: Executes
git add .
to stage all changes- All modified files are automatically staged
- All new files are automatically staged
- Deleted files are automatically staged
-
Status Display: Shows
git status
output for review -
User Confirmation: Prompts "Do you want to continue? (y/n)" before proceeding
-
Remote Setup: Adds remote repositories if not already configured
-
Commit Operation:
- Commits all staged changes using the configured commit message
- Uses
git commit -am "message"
(commits all tracked file changes) - Message priority: CLI override > repo default >
backup-YYYY-MM-DD
-
Pull Operation (unless force mode):
- Executes
git pull <remote> main
to sync with remote changes - Uses any additional pull arguments specified with
--pull
- Executes
-
Push Operation:
- Executes
git push <remote> main
to upload local changes - In force mode: Uses
git push -f <remote> main
- Uses any additional push arguments specified with
--push
- Executes
When using status-only mode, the tool:
- Skips all write operations (no commits, pulls, or pushes)
- Shows repository status for each configured repository
- Lists repositories with no changes
- Highlights repositories with uncommitted changes
- All files are committed: The tool uses
git add .
andgit commit -am
, meaning ALL changes in the repository are staged and committed - Path pattern support: Use
-p <PathGlob>
to target specific files or directories, though all matching files are still processed together - Automatic operations: Once confirmed, all git operations (add, commit, pull, push) happen automatically
- Multi-remote support: Each repository can push to multiple remote repositories sequentially
- Python Environment Setup: Ensures Python3 and PyYAML are available, creating virtual environments if needed
- Configuration Validation: Validates
config.yaml
with descriptive error messages for any issues - Configuration Loading: Reads the validated configuration and substitutes environment variables
- Repository Discovery: Parses the YAML configuration to find all defined repositories
- Filtering: Applies any regex filters specified via command line
- User Confirmation: Prompts user to confirm before proceeding with operations
- Git Configuration: Sets global git configuration from the YAML file
- Repository Processing: For each repository:
- Creates local directory if it doesn't exist
- Clones from remote if local repo doesn't exist
- Creates remote repositories if they don't exist (requires GitHub CLI)
- Shows git status and prompts for confirmation
- Commits, pulls, and pushes changes
repos
- Main executable scriptconfig.yaml
- Configuration file with template and documentationfunctions
- Helper functions for git operations and YAML parsingyaml_lookup.py
- Python script for YAML key lookup with validationyaml_parse.py
- Python script for complete YAML parsing and exporttests/
- Test suite for configuration validation
This tool is particularly useful for GitHub-based workflows:
- Backup Repositories: Maintain automatic backups across different GitHub accounts or organizations
- Fork Synchronization: Keep your GitHub fork in sync with an upstream repository
- Environment Deployment: Deploy the same codebase to multiple GitHub repositories for different environments
- Mirror Repositories: Maintain GitHub mirrors for redundancy or different access patterns
Note: While the tool can work with any Git remote URLs, automatic repository creation and some advanced features require GitHub repositories and the GitHub CLI.
- Configuration Validation: Early validation with specific error messages (e.g., "Template placeholder found: ${YOUR_GITHUB_USERNAME}")
- User Confirmation: Prompts before performing operations
- Status Checking: Shows git status before committing
- Error Handling: Colored output with checkmarks (✓/✗) to highlight successful and failed operations
The tool automatically manages Python dependencies:
- Creates temporary virtual environments if needed
- Installs
pyyaml
if not available - Reuses existing temporary environments when possible
- Package Mapping: Handles cases where pip package names differ from import names:
pyyaml
package → imports asyaml
The project includes comprehensive automated tests for configuration validation:
# Run all validation tests
./tests/run_tests.sh
# Test individual configurations manually
cd tests
python3 ../yaml_lookup.py valid_test_config_sub.yaml repos
python3 ../yaml_lookup.py test_config_sub.yaml repos # Should fail
Tests cover:
- Configuration validation with template placeholders (should fail)
- Valid configurations (should pass)
- Mixed configurations with commented templates (should pass)
- Python/PyYAML environment setup
- Descriptive error messages
See tests/README.md
for detailed testing documentation.
Configuration Validation Errors:
- Template placeholders found: Replace all
<PLACEHOLDER>
values in config.yaml - Missing required section: Uncomment and configure the
config:
andrepos:
sections - Invalid YAML syntax: Check indentation and syntax
Python Environment Issues:
- PyYAML not found: The tool automatically installs PyYAML in a virtual environment
- Permission errors: Ensure you have write access to
/tmp
for virtual environments
Git Operation Issues:
- Authentication failed: Ensure GitHub CLI (
gh
) is logged in:gh auth login
- Repository not found: Check GitHub repository URLs and permissions
- Push rejected: May need to pull first or use force option (use with caution)
- Repository creation failed: Ensure GitHub CLI has proper permissions and is authenticated
GitHub-Specific Issues:
- Non-GitHub URLs: Some features may not work with non-GitHub repositories
- Organization repositories: Ensure you have appropriate permissions for organization repos
- Private repositories: Check that GitHub CLI has access to private repositories
- Run
./repos --help
to see all available options - Check
./repos -s
to see repository status without making changes - Review configuration with detailed error messages from validation
Feel free to submit issues and pull requests to improve the tool.
This project is licensed under the MIT License - see the LICENSE file for details.