How to Backup All Your GitHub Repositories (Automatic & Manual)

Losing access to your GitHub repositories can halt your entire development workflow. Whether it is an accidental deletion, a compromised account, or a GitHub outage, having a reliable way to backup GitHub repositories is essential for any developer or engineering team. This guide walks you through every method available to backup all your GitHub repositories, from quick manual clones to fully automated solutions that run on a schedule.
If you are looking for a broader overview of GitHub backup strategies, start with our complete guide to backing up GitHub.
Why You Need to Backup Your GitHub Repositories
GitHub is not a backup service. It is a hosting platform, and there is a meaningful difference. GitHub's terms of service do not guarantee data durability the way a dedicated backup solution does. Here are real scenarios that catch developers off guard:
Accidental repository deletion by a team member with admin access
Account compromise where an attacker wipes or overwrites repositories
GitHub outages that block access to your code during critical deployments
Organization policy changes that remove your access to private repos
Billing lapses that lock you out of private repositories on paid plans
A proper GitHub backup repository strategy means you always have an independent copy of your code, branches, tags, issues metadata, and history stored somewhere you control.
Backing Up a Single GitHub Repository
Before tackling bulk backups, it helps to understand what a complete single-repo backup looks like. A simple git clone only gives you the default branch and remote tracking branches. For a true backup, you want a bare mirror clone.
Mirror Clone a Single Repo
git clone --mirror https://github.com/your-username/your-repo.git
The --mirror flag creates a bare repository that includes all branches, tags, and refs. This is the most complete clone you can make of a git backup repo. The resulting directory will be named your-repo.git and contains the full history.
To update an existing mirror clone later:
cd your-repo.git
git remote update
This pulls down any new commits, branches, or tags since the last backup. It is efficient because git only transfers the delta.
How to Backup All GitHub Repositories at Once
Cloning repositories one at a time does not scale. If you have dozens or hundreds of repos across personal accounts and organizations, you need automation. The GitHub REST API makes it straightforward to list every repository you have access to and clone them in bulk.
Step 1: Create a Personal Access Token
Before you can use the GitHub API to list and clone private repositories, you need a Personal Access Token (PAT):
Go to GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)
Click Generate new token (classic)
Select the
reposcope for full access to private and public repositoriesCopy the token immediately. GitHub will not show it again.
For fine-grained tokens, grant Repository access > All repositories with at least Contents: Read-only permission.
Step 2: List All Your Repositories Using the GitHub API
The GitHub REST API endpoint GET /user/repos returns all repositories the authenticated user has access to. Here is how to fetch them:
curl -s -H "Authorization: token YOUR_GITHUB_PAT" \
"https://api.github.com/user/repos?per_page=100&page=1&type=all" \
| jq -r '.[].clone_url'
This returns clone URLs for up to 100 repositories per page. The type=all parameter ensures you get repositories you own, collaborate on, and are a member of through organizations.
Step 3: Full Backup Script for All GitHub Repositories
Here is a working bash script that lists all repositories using the GitHub API, handles pagination, and performs mirror clones of every repo:
#!/usr/bin/env bash
set -euo pipefail
Configuration
GITHUB_TOKEN="YOUR_GITHUB_PAT"
BACKUP_DIR="$HOME/github-backups/$(date +%Y-%m-%d)"
API_URL="https://api.github.com/user/repos"
PER_PAGE=100
mkdir -p "$BACKUP_DIR"
echo "Starting GitHub backup to $BACKUP_DIR"
page=1
while true; do
Fetch a page of repositories
repos=$(curl -s -H "Authorization: token $GITHUB_TOKEN"
"${API_URL}?per_page=${PER_PAGE}&page=${page}&type=all&affiliation=owner,collaborator,organization_member")
Break if no more repos
count=$(echo "$repos" | jq '. | length')
if [ "$count" -eq 0 ]; then
break
fi
Extract clone URLs and repo names
echo "$repos" | jq -r '.[] | "(.name) (.clone_url)"' | while read -r name url; do
# Replace https URL with authenticated URL
auth_url=$(echo "$url" | sed "s|https://|https://${GITHUB_TOKEN}@|")
target="$BACKUP_DIR/$name.git"
if [ -d "$target" ]; then
echo "Updating existing backup: $name"
git -C "$target" remote update
else
echo "Cloning: $name"
git clone --mirror "$auth_url" "$target"
fi
done
page=$((page + 1))
done
echo "Backup complete. $(find "$BACKUP_DIR" -maxdepth 1 -type d -name '*.git' | wc -l) repositories backed up."
Save this script as github-backup.sh, run chmod +x github-backup.sh, and execute it. It will create a date-stamped directory with mirror clones of every repository you have access to.
For organization-specific backups, replace the API endpoint with:
API_URL="https://api.github.com/orgs/YOUR_ORG_NAME/repos"
Handling Edge Cases in GitHub Repository Backups
A basic mirror clone handles most scenarios, but production repositories often have complications that a simple script misses.
Large Repositories and Git LFS
Repositories that use Git Large File Storage (LFS) store large binary files as pointers in git, with the actual content on a separate LFS server. A standard git clone --mirror will copy the pointer files but not the LFS objects.
To include LFS content in your backup:
# After mirror cloning, fetch LFS objects
cd your-repo.git
git lfs fetch --all
This downloads every LFS object across all branches. LFS content can be substantial, so make sure your backup destination has sufficient storage. Without this step, restoring from backup would give you pointer files instead of the actual binaries.
Git Submodules
If your repositories use submodules, a mirror clone does not automatically include the submodule content. Each submodule is a separate repository that needs its own backup. You can parse the .gitmodules file to identify submodule URLs:
git config -f .gitmodules --get-regexp url | awk '{print $2}'
Add those repositories to your backup list to ensure full coverage.
Wiki Repositories
GitHub wikis are stored as separate git repositories. If your project uses the built-in wiki, its repository URL follows the pattern:
https://github.com/your-username/your-repo.wiki.git
The GitHub API does not list wiki repos separately, so you need to check for their existence and clone them alongside the main repository. Add this to your backup script:
wiki_url="${url%.git}.wiki.git"
wiki_target="$BACKUP_DIR/${name}.wiki.git"
if git ls-remote "$wiki_url" &>/dev/null; then
echo "Cloning wiki: $name"
git clone --mirror "$wiki_url" "$wiki_target"
fi
Handling Rate Limits
The GitHub API enforces rate limits of 5,000 requests per hour for authenticated users. If you have hundreds of repositories, your script might hit this limit. Add rate limit checking:
remaining=$(curl -s -H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/rate_limit | jq '.resources.core.remaining')
if [ "$remaining" -lt 10 ]; then
echo "Rate limit nearly exhausted. Waiting for reset..."
sleep 3600
fi
Private vs Public Repos and Authentication
The authentication method you choose for your git backup repo workflow affects both security and automation capabilities.
Personal Access Tokens (PATs)
PATs are the simplest way to authenticate for backups. They work over HTTPS and can be embedded in clone URLs. The downside is that a PAT with repo scope grants full read and write access. For backup purposes, a fine-grained token with read-only permissions is more secure.
Store tokens in environment variables or a secrets manager, never hardcoded in scripts that get committed to version control.
SSH Keys
SSH key authentication avoids embedding tokens in URLs. Generate a dedicated key pair for backups:
ssh-keygen -t ed25519 -f ~/.ssh/github_backup -C "backup-key"
Add the public key as a deploy key (read-only) on each repository, or add it to your GitHub account for access to all repos. Then use SSH clone URLs in your script:
git clone --mirror [email protected]:your-username/your-repo.git
SSH keys are preferable for automated systems because they can be scoped to specific machines and revoked independently.
GitHub App Authentication
For organizations managing backups at scale, a GitHub App provides the most granular access control. Apps use short-lived installation tokens that automatically expire, reducing the risk of credential leakage. This is the approach that dedicated GitHub backup tools typically use.
Automating Backups with Cron Jobs
Running the backup script manually defeats the purpose. A cron job ensures your backups happen on a reliable schedule without human intervention.
Setting Up a Cron Job
Open your crontab:
crontab -e
Add a daily backup at 2 AM:
0 2 * * * /path/to/github-backup.sh >> /var/log/github-backup.log 2>&1
For weekly backups every Sunday:
0 2 * * 0 /path/to/github-backup.sh >> /var/log/github-backup.log 2>&1
Limitations of Cron-Based Backups
Cron jobs work, but they come with real operational overhead:
No monitoring or alerting. If the script fails silently, you will not know until you need the backup.
No retention management. Old backups pile up and consume disk space unless you add cleanup logic.
Server dependency. The cron job only runs if the machine is on and connected. A laptop that is closed at 2 AM will miss the backup.
No backup verification. There is no built-in check that the backup is actually complete and restorable.
Manual maintenance. New repositories are only included if the script uses the API to discover them. Hardcoded repo lists go stale.
No encryption or offsite storage. You need additional scripting to encrypt backups and upload them to S3 or another remote location.
For a deeper comparison of backup utilities and approaches, see our guide to GitHub backup utils.
Using a Dedicated Backup Tool Instead
Building and maintaining your own backup scripts works for small setups, but it quickly becomes a burden as your repository count grows or when you need guarantees about backup completeness and reliability.
A dedicated backup tool like Gitbackups eliminates all of the manual work covered in this guide:
Automatic repository discovery. Connect your GitHub account and Gitbackups finds every repository, including new ones added after setup.
Scheduled mirror backups. Choose your backup frequency and Gitbackups runs on schedule, with no cron jobs or servers to manage.
S3-compatible storage. Backups are stored in your own S3-compatible storage, giving you full control and ownership of your data.
Handles edge cases. Git LFS, submodules, wiki repos, and large repositories are all handled without extra configuration.
Private and public repos. Authenticate with a PAT, SSH key, or access token. Gitbackups supports all standard GitHub authentication methods.
Monitoring and alerts. Get notified if a backup fails instead of discovering the problem when you need a restore.
Backup verification. Every backup is verified to ensure completeness and integrity.
Instead of spending time writing scripts, debugging API pagination, and managing cron jobs, you can have reliable backups of all your GitHub repositories running in minutes.
Summary: Choosing Your Backup Approach
For most developers and teams, the time spent building and maintaining custom backup scripts is better spent writing code. A dedicated solution like Gitbackups handles repository discovery, scheduling, storage, edge cases, and monitoring so you do not have to.
Whether you choose to script it yourself or use a managed tool, the important thing is that you have a backup strategy in place. Your GitHub repositories contain months or years of work. Protect them accordingly.