Skip to content

somaz94/multi-git-mirror

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

Multi Git Mirror

Continuous Integration License: MIT Latest Tag Top Language GitHub Marketplace

A Go-based GitHub Action that mirrors repositories to multiple Git hosting providers — GitLab, GitHub, Bitbucket, AWS CodeCommit, and more — in a single step.


Features

  • Multi-target mirroring in a single workflow step
  • Auto-detect provider from URL (GitLab, GitHub, Bitbucket, CodeCommit)
  • Selective branch mirroring or mirror all branches
  • Exclude specific branches from mirroring
  • Tag mirroring support
  • Force push option for exact replication
  • Multiple authentication methods (token, app password, SSH key)
  • Parallel mirroring to multiple targets concurrently
  • Retry logic with configurable count and delay
  • Dry run mode with remote connectivity pre-check (git ls-remote)
  • JSON result output for downstream steps
  • Credential masking in all log output

For detailed documentation, see the docs/ folder: Authentication | Configuration | Examples | Development


Usage


Basic — Mirror to GitLab

steps:
  - name: Checkout
    uses: actions/checkout@v6
    with:
      fetch-depth: 0

  - name: Mirror to GitLab
    uses: somaz94/multi-git-mirror@v1
    with:
      targets: |
        gitlab::https://gitlab.com/myorg/myrepo.git
      gitlab_token: ${{ secrets.GITLAB_TOKEN }}

Multi-target — GitLab + CodeCommit

- name: Mirror to multiple targets
  uses: somaz94/multi-git-mirror@v1
  with:
    targets: |
      gitlab::https://gitlab.com/myorg/myrepo.git
      codecommit::https://git-codecommit.us-east-1.amazonaws.com/v1/repos/myrepo
    gitlab_token: ${{ secrets.GITLAB_TOKEN }}
    mirror_branches: 'main,develop'
    mirror_tags: 'true'

Mirror to Bitbucket

- name: Mirror to Bitbucket
  uses: somaz94/multi-git-mirror@v1
  with:
    targets: |
      bitbucket::https://bitbucket.org/myorg/myrepo.git
    bitbucket_username: ${{ secrets.BITBUCKET_USERNAME }}
    bitbucket_api_token: ${{ secrets.BITBUCKET_API_TOKEN }}

With SSH Key

- name: Mirror via SSH
  uses: somaz94/multi-git-mirror@v1
  with:
    targets: |
      generic::git@custom-git.example.com:org/repo.git
    ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}

Dry Run with Output

- name: Mirror (dry run)
  uses: somaz94/multi-git-mirror@v1
  id: mirror
  with:
    targets: |
      gitlab::https://gitlab.com/myorg/myrepo.git
    gitlab_token: ${{ secrets.GITLAB_TOKEN }}
    dry_run: 'true'
    debug: 'true'

- name: Check results
  run: |
    echo "Result: ${{ steps.mirror.outputs.result }}"
    echo "Mirrored: ${{ steps.mirror.outputs.mirrored_count }}"
    echo "Failed: ${{ steps.mirror.outputs.failed_count }}"

In Release Workflow

name: Release and Mirror

on:
  push:
    tags:
      - "v[0-9]+.[0-9]+.[0-9]+"

jobs:
  release-and-mirror:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Create GitHub release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.ref_name }}

      - name: Mirror to backup providers
        uses: somaz94/multi-git-mirror@v1
        with:
          targets: |
            gitlab::https://gitlab.com/myorg/myrepo.git
            bitbucket::https://bitbucket.org/myorg/myrepo.git
          gitlab_token: ${{ secrets.GITLAB_TOKEN }}
          bitbucket_username: ${{ secrets.BITBUCKET_USERNAME }}
          bitbucket_api_token: ${{ secrets.BITBUCKET_API_TOKEN }}

Inputs

Input Description Required Default
targets Mirror target URLs (newline-separated, provider::url or auto-detect) Yes -
gitlab_token GitLab personal access token No ''
github_token GitHub personal access token No ''
bitbucket_username Bitbucket username for app password auth No ''
bitbucket_api_token Bitbucket API token No ''
ssh_private_key SSH private key for SSH-based authentication No ''
mirror_branches Branches to mirror (comma-separated, or all) No all
mirror_tags Mirror tags No true
force_push Use force push No true
dry_run Dry run mode with remote pre-check No false
retry_count Number of retry attempts on push failure No 0
retry_delay Delay in seconds between retries No 5
exclude_branches Branches to exclude (comma-separated) No ''
parallel Mirror to targets in parallel No false
debug Enable debug logging No false

Outputs

Output Description Example
result JSON array with mirror results per target [{"target":{...},"success":true,"message":"mirrored successfully"}]
mirrored_count Number of successfully mirrored targets 2
failed_count Number of failed mirror targets 0

Target Format

Targets are specified one per line. You can explicitly set the provider or let it auto-detect from the URL:

provider::url          # explicit provider
url                    # auto-detect from URL

Supported Providers

Provider Auth Method Example URL
gitlab OAuth2 token https://gitlab.com/org/repo.git
github x-access-token https://github.com/org/repo.git
bitbucket Username + App password https://bitbucket.org/org/repo.git
codecommit IAM / credential-helper https://git-codecommit.us-east-1.amazonaws.com/v1/repos/repo
generic SSH key or URL as-is git@custom-git.example.com:org/repo.git

Why?

Many teams need to keep repository mirrors in sync across multiple Git providers — for disaster recovery, CI/CD across platforms, compliance, or migration. This action replaces fragile shell scripts with a single, configurable step that handles authentication, branch/tag selection, and multi-target mirroring out of the box.


Project Structure

.
├── cmd/
│   └── main.go                  # Entry point
├── internal/
│   ├── config/
│   │   ├── config.go            # Configuration loading & target parsing
│   │   └── config_test.go       # Config tests
│   ├── mirror/
│   │   ├── mirror.go            # Mirror logic, retry, parallel, auth URL injection
│   │   ├── ssh.go               # SSH key setup/cleanup
│   │   └── mirror_test.go       # Mirror tests
│   └── output/
│       └── output.go            # GitHub Actions output writer
├── .github/
│   └── workflows/               # CI/CD workflows (10 files)
├── action.yml                   # Action metadata
├── Dockerfile                   # Multi-stage Docker build
├── Makefile                     # Build targets
├── cliff.toml                   # git-cliff changelog config
└── go.mod

Development


Prerequisites

  • Go 1.24+
  • Docker (for container builds)

Build

make build

Test

make test

Coverage

make cover

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


License

This project is licensed under the MIT License — see the LICENSE file for details.