How to backup a Git repository
Backing up Git repositories protects against data loss, accidental deletions, and hosting outages.
As the creator of CoreUI with over 25 years of version control experience since 2000, I’ve maintained backup strategies for codebases with years of history and hundreds of contributors.
The most reliable approach uses git bundle for portable backups or bare clones for full mirrors, both capturing all branches, tags, and history.
A good backup strategy runs automatically on a schedule.
Create a complete backup using git bundle.
git bundle create repo-backup-$(date +%Y%m%d).bundle --all
git bundle packages the entire repository into a single file. The --all flag includes all branches and tags. The $(date +%Y%m%d) appends today’s date to the filename. Bundle files are portable and self-contained.
Verifying a Bundle
Check the backup is valid before storing it.
git bundle verify repo-backup-20260311.bundle
git bundle list-heads repo-backup-20260311.bundle
verify confirms the bundle is complete and not corrupted. list-heads shows all branches and tags contained. Always verify before relying on a backup.
Restoring from a Bundle
Restore the repository from a backup file.
git clone repo-backup-20260311.bundle restored-repo
cd restored-repo
git branch -a
git clone works directly with bundle files. All history, branches, and tags restore correctly. The -a flag verifies all branches are present after restoration.
Creating a Bare Clone Mirror
Mirror a repository to a backup server.
git clone --bare https://github.com/username/repo.git repo.git
cd repo.git
git remote update
A bare clone contains only the Git objects with no working tree. It’s ideal for backup servers. git remote update fetches all new commits, branches, and tags from the original.
Automating Backups with a Script
Schedule regular automated backups.
#!/bin/bash
# backup-repo.sh
REPO_URL="https://github.com/username/repo.git"
BACKUP_DIR="/backups/git"
DATE=$(date +%Y%m%d-%H%M%S)
mkdir -p "$BACKUP_DIR"
cd /tmp
git clone --bare "$REPO_URL" "repo-$DATE.git"
cd "repo-$DATE.git"
git bundle create "$BACKUP_DIR/repo-$DATE.bundle" --all
cd /tmp
rm -rf "repo-$DATE.git"
find "$BACKUP_DIR" -name "*.bundle" -mtime +30 -delete
echo "Backup completed: repo-$DATE.bundle"
The script clones bare, creates a bundle, moves it to the backup directory, then cleans up. The find command deletes backups older than 30 days. Schedule with cron: 0 2 * * * /path/to/backup-repo.sh.
Pushing to a Secondary Remote
Mirror to a second hosting service automatically.
git remote add backup https://gitlab.com/username/repo.git
git push backup --all
git push backup --tags
A secondary remote on a different hosting provider (GitHub → GitLab) provides geographic redundancy. Push all branches and tags after significant work or on a schedule. This protects against a single hosting provider going down.
Best Practice Note
This is the same backup strategy we use for CoreUI repositories to ensure no history is ever lost. The 3-2-1 rule applies to code too: three copies, two different media, one offsite. Combine bundle backups on local storage with a mirror on a second hosting service. Test restoring from backups periodically - an untested backup is not a backup. For organizations, use automated scripts run by CI/CD or cron jobs so backups never depend on manual effort.



