How to Mirror a Bare Git Repository Backup in Python

Run a git clone --bare subprocess to create a timestamped bare-repo backup folder with error handling.

Easy Python 3.9+ Aug 9, 2026 Git + Python 13 views 0 copies

Python code

26 lines
Python 3.9+
import subprocess
import shlex
from pathlib import Path
from datetime import datetime


def mirror_bare_repo(source_url: str, backup_dir: str) -> str:
    """Mirror a bare git repository to a timestamped backup folder."""
    backup_path = Path(backup_dir)
    backup_path.mkdir(parents=True, exist_ok=True)

    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    target_path = backup_path / f"{Path(source_url).stem}_{timestamp}"

    cmd = shlex.split(f"git clone --bare {source_url} {target_path}")
    result = subprocess.run(cmd, capture_output=True, text=True)

    if result.returncode == 0:
        return f"Mirrored {source_url} to {target_path}"
    else:
        return f"Failed: {result.stderr.strip()}"


if __name__ == "__main__":
    status = mirror_bare_repo("git@github.com:example/project.git", "/tmp/backups")
    print(status)

Output

stdout
Mirrored git@github.com:example/project.git to /tmp/backups/project_20250321_143005

How it works

This script uses subprocess.run with shlex.split to safely build and execute the git clone --bare command. The --bare flag creates a repository without a working tree, perfect for server-side backups. Path handles cross-platform path creation, and the timestamp prevents collisions. The return code check reports failures with captured stderr, making it robust for automation.

Common mistakes

  • Forgetting `--bare`, which creates a full checkout instead of a bare mirror.
  • Not capturing stderr, so failures silently pass.
  • Using string concatenation instead of `shlex.split`, risking shell injection.
  • Hardcoding timestamps that can collide if run twice in the same second.

Variations

  1. Add `git push --mirror` to a remote after cloning instead of local backup.
  2. Use `pathlib.Path.with_name` with a random UUID to avoid timestamp collisions.

Real-world use cases

  • Scheduled cron jobs that backup all remote repos nightly to an archive server.
  • Pre-migration snapshots before rewriting Git history or splitting a monorepo.
  • Drift detection by comparing current bare clones against previous backups.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Git + Python

Related tutorials and quizzes for this topic.