This system automatically mirrors GitHub repositories to your local machine, preserving all branches, tags, and refs. The mirrors are kept in sync with daily automatic updates via cron.
- Mirror multiple GitHub repositories with a single command
- Preserves all branches and tags (no pruning)
- Automatic daily updates at midnight via cron
- Detailed logging of all backup operations
- Automatic log rotation (keeps last 30 days)
- Color-coded console output for easy monitoring
- Handles both initial cloning and incremental updates
opennav_repo_backups/
├── BACKUP_REPOS.TXT # List of repositories to mirror
├── mirror_repos.sh # Main backup script
├── setup_cron.sh # Cron setup script
├── README.md # This file
├── mirrors/ # Mirrored repositories (created automatically)
│ ├── ros-navigation_navigation2.git/
│ └── ros-navigation_docs.nav2.org.git/
└── logs/ # Backup logs (created automatically)
└── mirror_YYYYMMDD_HHMMSS.log
Edit BACKUP_REPOS.TXT and add the repositories you want to mirror (one per line):
ros-navigation/navigation2
ros-navigation/docs.nav2.org
Format: owner/repository
You can add comments by starting a line with #:
# ROS Navigation repositories
ros-navigation/navigation2
ros-navigation/docs.nav2.org
# Additional repos
another-org/another-repo
Run the cron setup script:
./setup_cron.shThis will configure a cron job to run the backup script daily at midnight (00:00).
You can run an immediate backup without waiting for the cron schedule:
./mirror_repos.shTo run a backup manually at any time:
./mirror_repos.sh- Edit
BACKUP_REPOS.TXT - Add new repository in the format
owner/repository - Save the file
The new repository will be included in the next scheduled backup, or you can run ./mirror_repos.sh immediately.
Logs are stored in the logs/ directory with timestamps. To view the most recent log:
ls -t logs/ | head -1 | xargs -I {} cat logs/{}Or view all recent logs:
ls -lht logs/To verify the cron job is installed:
crontab -l | grep mirror_repos.shTo view cron execution logs:
# Ubuntu/Debian
grep CRON /var/log/syslog | grep mirror_repos
# Systems with systemd
journalctl -u cron | grep mirror_reposTo stop automatic backups:
crontab -eThen delete the line containing mirror_repos.sh, save and exit.
- The script reads all repositories from
BACKUP_REPOS.TXT - For each repository:
- First time: Clones the repository as a mirror using
git clone --mirror - Subsequent runs: Updates the existing mirror using
git remote update
- First time: Clones the repository as a mirror using
- No pruning: All branches and refs are preserved, even if deleted from the remote
- Each operation is logged with timestamps
A mirror clone (git clone --mirror) creates a bare repository that includes:
- All branches
- All tags
- All refs
- All remote tracking information
This is ideal for backups as it captures the complete repository state.
Mirrors are stored in the mirrors/ directory with the naming format:
owner_repository.git
For example:
ros-navigation/navigation2→mirrors/ros-navigation_navigation2.git/
To create a working copy from a mirror:
git clone mirrors/ros-navigation_navigation2.git/ working-copyTo see all branches in a mirror:
cd mirrors/ros-navigation_navigation2.git/
git branch -aTo see all tags:
cd mirrors/ros-navigation_navigation2.git/
git tag -lIf you need to push a mirror to another GitHub account or Git server:
cd mirrors/ros-navigation_navigation2.git/
git push --mirror https://github.com/your-account/new-repo.gitIf you get permission denied errors, make scripts executable:
chmod +x mirror_repos.sh setup_cron.sh-
Check cron is installed and running:
systemctl status cron
-
Verify the cron job exists:
crontab -l
-
Check system logs for cron errors:
grep CRON /var/log/syslog
Check the latest log file in logs/ for error messages. Common issues:
- Network connectivity problems
- Repository no longer exists or is private
- Insufficient disk space
Monitor disk usage as mirrors can grow large:
du -sh mirrors/Edit the cron job to run at a different time:
crontab -eModify the schedule (format: minute hour day month weekday):
0 0 * * *- Midnight daily (default)0 2 * * *- 2:00 AM daily0 0 * * 0- Midnight every Sunday0 */6 * * *- Every 6 hours
Edit mirror_repos.sh and change the BACKUP_DIR variable:
BACKUP_DIR="/path/to/custom/backup/location"Logs older than 30 days are automatically deleted. To change this, edit the cleanup line in mirror_repos.sh:
find "$LOG_DIR" -name "mirror_*.log" -type f -mtime +30 -deleteChange +30 to your desired number of days.
To verify a mirror is healthy:
cd mirrors/ros-navigation_navigation2.git/
git fsck --full- Regularly verify backups are running (check logs weekly)
- Test restoration occasionally by cloning from mirrors
- Monitor disk space usage
- Keep the backup directory on a separate disk/partition for better reliability
- Consider additional offsite backups for critical repositories
These scripts are provided as-is for backup purposes.
For issues or questions:
- Check the logs in
logs/directory - Review the troubleshooting section above
- Ensure scripts have execute permissions
- Verify cron is running correctly