forgejo-batch-migrate

module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 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

Note: Pre-built binaries are not published yet. Build from source for now; this section will be replaced with download instructions once tagged releases are available.

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

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
Mirror every repo of another Forgejo/Gitea user

Use --mirror to keep the destination in sync with the source instead of a one-time copy.

forgejo-batch-migrate \
  --source-type gitea \
  --source-url https://gitea.example.com \
  --source-user alice \
  --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
Batch config

For repeatable runs, describe the work in a YAML file and pass --config:

forgejo-batch-migrate --config examples/nightly.yaml

See examples/nightly.yaml. Precedence is: built-in defaults < config defaults < per-job fields < explicitly-set CLI flags.

target:
  url: https://codefloe.com
  owner: mirrors
  create_org: true
run:
  concurrency: 2
  rate_limit: 30
  skip_existing: true
defaults:
  issues: true
  pull_requests: true
jobs:
  - source: { type: github, org: acme }
  - source: { type: gitlab, url: https://gitlab.com, repos: [group/proj] }
    private: true

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.

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.

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