Mirror every GitHub repository you can access into local bare git mirrors.
Project description
GitHub Backup Sync
github_backup_sync.py mirrors every GitHub repository your account can access into bare --mirror clones, grouping sources and forks separately. The project was inspired after watching ThePrimeTime's reminder about GitHub bans, highlighting why local backups matter. Plenty of alternative backup tools exist, but I wanted something simple that relies on the GitHub CLI for authentication so I never have to juggle API tokens directly.
Table of Contents
Requirements
uv(recommended; the shebang runs the script throughuv run)- GitHub CLI (
gh) authenticated withgh auth login gitand, optionally,git-lfsif you use the--lfsflag
The script also works inside a manual virtual environment if you install the same dependencies listed in the script header, but uv provides the fastest startup and dependency management.
Usage
./github_backup_sync.py --root /path/to/mirrors [--https] [--prune] [--skip-forks] [--workers 4]
--rootpoints at the backup directory.--httpsswitches from SSH to HTTPS remotes (still using theghtoken).--pruneremoves local mirrors that no longer exist upstream.--skip-forksmirrors only non-fork repositories.--workerscontrols how many repositories sync in parallel (default: CPU-based).--limitis handy for smoke-testing with only a few repos.
The script automatically fetches a GitHub token from gh auth token, so you only need to keep the CLI logged in.
CLI Help
github_backup_sync.py --help output
Usage: github_backup_sync.py [OPTIONS]
Coordinate the CLI workflow for mirroring repositories.
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --root -r PATH Directory that will │
│ hold the mirror │
│ --https Use HTTPS remotes │
│ (token optional for │
│ public repos) │
│ --include-archived --exclude-archived Include archived │
│ repositories │
│ [default: │
│ include-archived] │
│ --prune Remove local mirrors │
│ that no longer exist │
│ upstream │
│ --lfs Fetch Git LFS │
│ objects after │
│ mirroring │
│ --sleep FLOAT RANGE Delay between │
│ [x>=0.0] repositories in │
│ seconds │
│ [default: 0.0] │
│ --limit INTEGER RANGE Process at most this │
│ [x>=1] many repositories │
│ --skip-forks Ignore forked │
│ repositories while │
│ mirroring │
│ --workers -w INTEGER RANGE Max concurrent │
│ [x>=1] mirror operations │
│ (default: based on │
│ CPU count) │
│ --help -h Show this message │
│ and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────╯
Layout
<root>/source/<owner>/<repo>.git
<root>/forks/<owner>/<repo>.git
All repositories are bare mirrors, suitable for backup purposes.
Working with Mirrors
Repositories under source/ and forks/ are bare --mirror clones, so they do not contain a checked-out working tree. Clone from a mirror path when you want editable files, for example:
git clone /srv/github-backups/source/basnijholt/dotfiles.git ~/dotfiles
You can also inspect a mirror directly without cloning by pointing Git commands at it, e.g. git --git-dir=/srv/github-backups/source/basnijholt/dotfiles.git log --oneline.
Automated Backups (cron)
You can schedule a daily sync via cron after installing the script somewhere on your $PATH:
0 3 * * * /usr/bin/env uv run /opt/github-backup-sync/github_backup_sync.py --root /srv/github-backups --https --prune --workers 4 >> /var/log/github-backup-sync.log 2>&1
This example runs every day at 03:00, performs a prune, and logs output. Adjust the path, flags, and worker count to suit your environment.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file github_backup_sync-0.1.0.tar.gz.
File metadata
- Download URL: github_backup_sync-0.1.0.tar.gz
- Upload date:
- Size: 8.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8603b0be43b9926d6b7023c9409496e9279bd7361d4091ec7f234249f42e39f7
|
|
| MD5 |
d4feafb4fa69692721a62dfb5daba65d
|
|
| BLAKE2b-256 |
1ac56d674b4dc9f60c39a6da0ae394f1086c3083f51b4ba14bbfe4a534c6b90f
|
Provenance
The following attestation bundles were made for github_backup_sync-0.1.0.tar.gz:
Publisher:
pythonpublish.yml on basnijholt/github-backup-sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
github_backup_sync-0.1.0.tar.gz -
Subject digest:
8603b0be43b9926d6b7023c9409496e9279bd7361d4091ec7f234249f42e39f7 - Sigstore transparency entry: 637757557
- Sigstore integration time:
-
Permalink:
basnijholt/github-backup-sync@4f247e4e0704a9f5c0da8acde1c2de0ae680640d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/basnijholt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pythonpublish.yml@4f247e4e0704a9f5c0da8acde1c2de0ae680640d -
Trigger Event:
release
-
Statement type:
File details
Details for the file github_backup_sync-0.1.0-py3-none-any.whl.
File metadata
- Download URL: github_backup_sync-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a2ac1881cd407a75c783a95e58a859b3b3b5d06be68dd12e88003a723be8c47
|
|
| MD5 |
43026cf94b213c6edac7e82c56ec72f1
|
|
| BLAKE2b-256 |
3b128676173346eb35cb2a814fd8144e67f674c359ecde23284fdc7f31cfb857
|
Provenance
The following attestation bundles were made for github_backup_sync-0.1.0-py3-none-any.whl:
Publisher:
pythonpublish.yml on basnijholt/github-backup-sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
github_backup_sync-0.1.0-py3-none-any.whl -
Subject digest:
0a2ac1881cd407a75c783a95e58a859b3b3b5d06be68dd12e88003a723be8c47 - Sigstore transparency entry: 637757562
- Sigstore integration time:
-
Permalink:
basnijholt/github-backup-sync@4f247e4e0704a9f5c0da8acde1c2de0ae680640d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/basnijholt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pythonpublish.yml@4f247e4e0704a9f5c0da8acde1c2de0ae680640d -
Trigger Event:
release
-
Statement type: