3.1 KiB
git-mirror
![Logo][./docs/icons/256x256/git-mirror.png]
Small Bash utility for mirroring a directory of local Git repositories to GitHub, GitLab, and Codeberg.
The repository currently contains a single script, git-mirror, which:
- scans a source directory for both standard repositories and bare repositories
- creates missing remote repositories on GitHub, GitLab, and Codeberg
- configures per-repository mirror remotes
- pushes branches and tags to each target service
Requirements
- Bash
gitcurlrealpathsedgreppassfor retrieving access tokens- SSH access configured for GitHub, GitLab, and Codeberg
Configuration
Edit the variables near the top of the script:
SOURCE_DIR="$(realpath "data/small/gitea/git/repositories/sean")"
THIRD_PARTY_GIT_USER="seanhly"
GITHUB_TOKEN="$(pass github-token)"
GITLAB_TOKEN="$(pass gitlab-token)"
CODEBERG_TOKEN="$(pass codeberg-token)"
What each value does:
SOURCE_DIR: directory containing the repositories to mirrorTHIRD_PARTY_GIT_USER: account or namespace used on all three servicesGITHUB_TOKEN: GitHub personal access token used for repository creationGITLAB_TOKEN: GitLab personal access token used for repository creationCODEBERG_TOKEN: Codeberg token used for repository creation
The script expects repository creation to happen over each service's HTTP API, but pushes happen over SSH. That means the tokens must be valid for API access and your local SSH keys must already be authorized on each hosting provider.
Usage
Make the script executable if needed:
chmod +x ./git-mirror
Run it from the repository root:
./git-mirror
What It Mirrors
The script handles both of these layouts inside SOURCE_DIR:
- non-bare repositories: directories containing a
.git/subdirectory - bare repositories: directories ending in
.git
For each repository it will:
- create the remote repository if it does not already exist
- replace any existing
github-mirror,gitlab-mirror, andcodeberg-mirrorremotes - push repository contents to each service
GitHub uses git push --mirror, which mirrors all refs. GitLab and Codeberg use explicit branch and tag pushes with prune enabled:
git push --prune <remote> 'refs/heads/*:refs/heads/*' 'refs/tags/*:refs/tags/*'
Operational Notes
- The script adds each processed repository to Git's global
safe.directorylist. - Remote repository creation is currently hard-coded as private on all providers.
- Existing mirror remotes are removed and re-added on every run.
- The script assumes the same username or namespace is valid on GitHub, GitLab, and Codeberg.
Caution
Run this only when you intend to synchronize local state to the target remotes.
git push --mirrorcan overwrite or delete remote refs that do not exist locally.--pruneon GitLab and Codeberg will remove remote branches that no longer exist locally.- Repository creation and push failures are only partially checked; review terminal output after each run.
License
This project is licensed under the GNU General Public License, version 3.
See LICENSE for the full text.