Skip to main content

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 through uv run)
  • GitHub CLI (gh) authenticated with gh auth login
  • git and, optionally, git-lfs if you use the --lfs flag

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]
  • --root points at the backup directory.
  • --https switches from SSH to HTTPS remotes (still using the gh token).
  • --prune removes local mirrors that no longer exist upstream.
  • --skip-forks mirrors only non-fork repositories.
  • --workers controls how many repositories sync in parallel (default: CPU-based).
  • --limit is 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

github_backup_sync-0.1.0.tar.gz (8.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

github_backup_sync-0.1.0-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

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

Hashes for github_backup_sync-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8603b0be43b9926d6b7023c9409496e9279bd7361d4091ec7f234249f42e39f7
MD5 d4feafb4fa69692721a62dfb5daba65d
BLAKE2b-256 1ac56d674b4dc9f60c39a6da0ae394f1086c3083f51b4ba14bbfe4a534c6b90f

See more details on using hashes here.

Provenance

The following attestation bundles were made for github_backup_sync-0.1.0.tar.gz:

Publisher: pythonpublish.yml on basnijholt/github-backup-sync

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file github_backup_sync-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for github_backup_sync-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0a2ac1881cd407a75c783a95e58a859b3b3b5d06be68dd12e88003a723be8c47
MD5 43026cf94b213c6edac7e82c56ec72f1
BLAKE2b-256 3b128676173346eb35cb2a814fd8144e67f674c359ecde23284fdc7f31cfb857

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page