forgejo-batch-migrate

module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2026 License: AGPL-3.0

README

forgejo-batch-migrate

Batch-migrate repositories from GitHub, GitLab or another Forgejo/Gitea instance into a target Forgejo instance.

The tool wraps Forgejo's own migration API (POST /api/v1/repos/migrate) and exposes every option the web migration assistant offers. It can migrate a whole source organization/group or user in one go, or a hand-picked list of repositories, and it makes conservative rate-limiting assumptions so large batches do not overwhelm either forge.

Features

  • Sources: GitHub, GitLab, Forgejo, Gitea, and plain git clone URLs.
  • Migrate an entire org/group (--source-org), a whole user (--source-user), or individual repos (--source-repo, repeatable).
  • All assistant options: issues, pull requests, labels, milestones, releases, wiki, LFS, mirror, private, and mirror interval.
  • Content options default to on; pass --issues=false (and friends) to skip.
  • Private source repositories are always created private on the target, regardless of the --private default.
  • Graceful degradation: options are automatically skipped for repositories whose source has that unit disabled (e.g. requesting releases when the source repo has releases turned off), so one disabled unit does not fail the whole migration.
  • Smart rate limiting: a global token bucket, a bounded worker pool, and automatic backoff on HTTP 429 (honoring Retry-After and GitHub's X-RateLimit-*).
  • One-shot flags for quick runs, or a YAML config describing many jobs for batch/cron use.
  • --dry-run resolves and prints the full plan without writing anything.

Install

The install script detects your OS and architecture, downloads and verifies the matching archive from the latest release, extracts the binary into a local bin directory (~/.local/bin by default), and creates an fbm alias next to it:

curl -fsSL https://codefloe.com/codefloe/forgejo-batch-migrate/raw/branch/main/install.sh | sh

Override the defaults with environment variables:

# pin a specific version
curl -fsSL https://codefloe.com/codefloe/forgejo-batch-migrate/raw/branch/main/install.sh | VERSION=v0.1.0 sh
# install somewhere else
curl -fsSL https://codefloe.com/codefloe/forgejo-batch-migrate/raw/branch/main/install.sh | INSTALL_DIR=/usr/local/bin sh
# skip creating the `fbm` alias
curl -fsSL https://codefloe.com/codefloe/forgejo-batch-migrate/raw/branch/main/install.sh | NO_ALIAS=1 sh

If the install directory is not on your PATH, the script prints the line to add.

Manual download

Download a pre-built archive from the latest release. Archives are published for Linux, macOS, and Windows (amd64 and arm64) as .tar.gz (Unix) and .zip (Windows), alongside a SHA256SUMS.txt for verification:

# Linux (amd64)
curl -LO https://codefloe.com/codefloe/forgejo-batch-migrate/releases/download/v0.1.0/forgejo-batch-migrate-linux-amd64.tar.gz
# Linux (arm64)
# curl -LO https://codefloe.com/codefloe/forgejo-batch-migrate/releases/download/v0.1.0/forgejo-batch-migrate-linux-arm64.tar.gz
# macOS (Intel)
# curl -LO https://codefloe.com/codefloe/forgejo-batch-migrate/releases/download/v0.1.0/forgejo-batch-migrate-darwin-amd64.tar.gz
# macOS (Apple Silicon)
# curl -LO https://codefloe.com/codefloe/forgejo-batch-migrate/releases/download/v0.1.0/forgejo-batch-migrate-darwin-arm64.tar.gz
tar -xzf forgejo-batch-migrate-linux-amd64.tar.gz
chmod +x forgejo-batch-migrate
# Windows (amd64): download the .zip and extract it
# curl -LO https://codefloe.com/codefloe/forgejo-batch-migrate/releases/download/v0.1.0/forgejo-batch-migrate-windows-amd64.zip

Or install with the Go toolchain:

go install codefloe.com/codefloe/forgejo-batch-migrate/cmd@latest
Build from source

Build from source with just:

just build
# binary at build/forgejo-batch-migrate

Or with the Go toolchain directly:

go build -o forgejo-batch-migrate ./cmd

Authentication

Provide a token for both forges. In order of preference:

  1. Environment variables SOURCE_TOKEN / FORGEJO_TARGET_TOKEN (recommended).
  2. Token files: --source-token-file / --target-token-file (e.g. a mounted secret).
  3. Literal flags --source-token / --target-token (discouraged: the value is visible in the process list and shell history, so the tool warns when you use them).
  • The target token is required for any real migration (a run without it fails fast; --dry-run is exempt).
  • A source token is strongly recommended even for public repositories: unauthenticated API access is rate-limited aggressively (e.g. GitHub allows only 60 requests/hour), so listing or migrating more than a few repos will otherwise stall. The tool warns when a source token is missing.

Usage

Migrate a whole GitHub organization
export SOURCE_TOKEN=ghp_...
export FORGEJO_TARGET_TOKEN=...
forgejo-batch-migrate \
  --source-type github \
  --source-org acme \
  --target-url https://codefloe.com \
  --target-owner acme-mirror \
  --create-org
Migrate a whole GitLab group (self-hosted)

Groups are addressed by their full path; subgroups are included automatically.

export SOURCE_TOKEN=glpat-...
forgejo-batch-migrate \
  --source-type gitlab \
  --source-url https://gitlab.example.com \
  --source-org platform/backend \
  --target-url https://codefloe.com \
  --target-owner backend \
  --create-org
Migrate a whole Forgejo organization
export SOURCE_TOKEN=...
export FORGEJO_TARGET_TOKEN=...
forgejo-batch-migrate \
  --source-type forgejo \
  --source-url https://codeberg.org \
  --source-org acme \
  --target-url https://codefloe.com \
  --target-owner acme \
  --create-org
Mirror selected repos from a single user

Pick individual repositories owned by one user with --source-repo, and use --mirror to keep the destination in sync with the source instead of a one-time copy.

forgejo-batch-migrate \
  --source-type forgejo \
  --source-url https://codefloe.com \
  --source-repo alice/dotfiles \
  --source-repo alice/notes \
  --target-url https://codefloe.com \
  --target-owner alice \
  --mirror --mirror-interval 24h0m0s
Migrate hand-picked repositories, code only

Pass --source-repo multiple times and switch off the metadata you do not want.

forgejo-batch-migrate \
  --source-type github \
  --source-repo acme/api \
  --source-repo acme/web \
  --target-url https://codefloe.com \
  --target-owner mirrors \
  --issues=false --pull-requests=false --wiki=false
Migrate arbitrary Git URLs

--source-type git mirrors any plain Git repository; pass full clone URLs.

forgejo-batch-migrate \
  --source-type git \
  --source-repo https://git.example.com/team/tool.git \
  --target-url https://codefloe.com \
  --target-owner mirrors
Preview without migrating

Add --dry-run to any invocation to list the resolved repositories and per-repo options without contacting the target for writes. This is the safe way to check what a whole-org migration would do before running it.

forgejo-batch-migrate \
  --source-type github --source-org acme \
  --target-url https://codefloe.com --target-owner mirrors \
  --dry-run

Options

Flag Config key Default Meaning
--issues issues true Migrate issues.
--pull-requests pull_requests true Migrate pull requests.
--labels labels true Migrate labels.
--milestones milestones true Migrate milestones.
--releases releases true Migrate releases.
--wiki wiki true Migrate the wiki.
--lfs lfs false Migrate Git LFS objects.
--mirror mirror false Set up the repo as a pull mirror.
--private private false Force the destination repo to be private.
--mirror-interval mirror_interval 8h0m0s Mirror sync interval.
--concurrency run.concurrency 2 Concurrent migrations.
--rate-limit run.rate_limit 30 Max API requests per minute.
--skip-existing run.skip_existing true Skip repos that already exist on the target.

Development

just vendor   # download + vendor + tidy modules
just fmt      # prettier + gofmt + gci
just lint     # golangci-lint
just test     # go test ./...
just build    # build the binary

Pre-commit hooks mirror the linters; run them with prek run -a.

License

AGPL-3.0

Directories

Path Synopsis
Command forgejo-batch-migrate batch-migrates repositories from GitHub, GitLab or Forgejo/Gitea into a target Forgejo instance.
Command forgejo-batch-migrate batch-migrates repositories from GitHub, GitLab or Forgejo/Gitea into a target Forgejo instance.
pkg
config
Package config parses the optional batch YAML configuration and merges it with built-in defaults into a fully-resolved migration plan.
Package config parses the optional batch YAML configuration and merges it with built-in defaults into a fully-resolved migration plan.
forgejo
Package forgejo talks to the target Forgejo instance: it triggers repository migrations and ensures the destination owner exists.
Package forgejo talks to the target Forgejo instance: it triggers repository migrations and ensures the destination owner exists.
httpx
Package httpx provides a small rate-limited, retrying HTTP client shared by the source-forge and target-Forgejo API clients.
Package httpx provides a small rate-limited, retrying HTTP client shared by the source-forge and target-Forgejo API clients.
migrate
Package migrate resolves a migration plan into concrete repository migrations and executes them against the target Forgejo instance with a bounded worker pool.
Package migrate resolves a migration plan into concrete repository migrations and executes them against the target Forgejo instance with a bounded worker pool.
source
Package source lists repositories from a source forge (GitHub, GitLab or Forgejo/Gitea) so they can be migrated into a target Forgejo instance.
Package source lists repositories from a source forge (GitHub, GitLab or Forgejo/Gitea) so they can be migrated into a target Forgejo instance.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL