A small CLI tool that allows one to easily migrate from Github to OpenCommit. https://opencommit.eu/opencommit/forgeport
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Martijn van der Kleijn 91caf99d16
All checks were successful
REUSE compliance check / test (pull_request) Successful in 6s
REUSE compliance check / test (push) Successful in 5s
fix: add missing CC0-1.0 license
Signed-off-by: Martijn van der Kleijn <martijn@opencommit.eu>
2026-09-17 23:41:32 +02:00
.forgejo/workflows ci: add reuse compliance check 2026-09-17 23:39:23 +02:00
LICENSES fix: add missing CC0-1.0 license 2026-09-17 23:41:32 +02:00
.gitignore chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
config.go chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
config_test.go chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
github.go chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
github_test.go chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
go.mod chore(deps): update module go.yaml.in/yaml/v3 to v3.0.5 2026-09-16 21:20:40 +00:00
go.sum chore(deps): update module go.yaml.in/yaml/v3 to v3.0.5 2026-09-16 21:20:40 +00:00
LICENSE chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
main.go chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
migrate.example.yaml chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
migrate.go chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
migrate_test.go chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00
README.md ci: add reuse compliance check 2026-09-17 23:39:23 +02:00
renovate.json Add renovate.json 2026-09-16 21:17:24 +00:00
REUSE.toml chore: change license to EUPL-1.2 and support REUSE spec 2026-09-17 23:14:14 +02:00

ForgePort

REUSE status

A small CLI tool that migrates repositories from GitHub to the OpenCommit Forgejo instance (opencommit.eu) using the Forgejo SDK.

The tool reads all of its configuration from a YAML file in the current working directory. It currently migrates a single repository (or a list of them, sequentially).

Requirements

  • Go 1.26 or later unless you use a pre-built binary
  • A Forgejo API token for the destination instance (create it in Forgejo → Settings → Applications → Generate New Token)
  • A GitHub personal access token (classic) for the source repositories

Usage

forgeport -config migrate.yaml  # defaults to `migrate.yaml` in the working directory
forgeport -dryrun               # resolve and print repos without migrating

-config defaults to migrate.yaml in the working directory. Each repository is migrated one at a time. Between migrations the tool sleeps a random pause of 515 seconds to avoid overloading the destination server. Run output is logged to stderr; the tool exits with a non-zero status if the configuration is invalid or any migration fails.

-dryrun resolves every repository (including user/org expansion) but does not contact Forgejo or migrate anything; it only prints which repositories would have been migrated.

Exiting example:

2026/01/01 12:00:00 migrating https://github.com/foo/bar -> opencommit/bar
2026/01/01 12:00:05 migrated: https://opencommit.eu/opencommit/bar

Note: migrate.yaml may contain secrets and is git-ignored. Commit migrate.example.yaml instead.

Limitations

The forgeport tool does currently not support migration of packages. You will have to do that yourself with a tool like Skopeo and a small bash script for example.

Configuration

Copy migrate.example.yaml to migrate.yaml in the directory you will run the tool from and edit it.

forgejo:
  url: https://opencommit.eu
  token: ""

defaults:
  token: ""
  include_private: true
  include_archived: false
  destination:
    owner: ""
    name: ""
  options:
    private: false
    description: ""
    wiki: true
    milestones: true
    labels: true
    issues: true
    pull_requests: true
    releases: true
    lfs: false
    lfs_endpoint: ""

repositories:
  - url: https://github.com/opencommit/opencommit.git
  # - url: my-github-user      # shorthand: migrate all of a user/org's source repos

Tokens

Secrets can live in the config file or their environment, with the environment winning:

Setting Environment variable Precedence
Forgejo token FORGEJO_TOKEN env > forgejo.token
GitHub token GITHUB_TOKEN env > repository token > defaults.token

The GitHub token is required: the Forgejo migration API authenticates against the source even for public repositories.

Sections

  • forgejo — connection settings for the destination instance.
    • url — Forgejo server URL, e.g. https://opencommit.eu. Required.
    • token — API token for the destination. Required unless FORGEJO_TOKEN is set.
  • defaults — global defaults applied to every repository (for every setting except the repository url).
    • token — default GitHub source token.
    • include_private — when expanding a user/org shorthand, include private repos the token has access to. Default: true.
    • include_archived — when expanding a user/org shorthand, include archived repos. Default: false.
    • destinationowner (required once resolved) and name (blank means derived from the url's repository name).
    • options — migration options: private, description, wiki, milestones, labels, issues, pull_requests, releases, lfs, lfs_endpoint.
  • repositories — list of repositories to migrate. Only url is required per entry; everything else can be inherited from defaults or overridden per entry with the same shape as defaults.
    • url is a git clone URL ending in .git, such as https://github.com/foo/bar.git. The tool exits with an error if a full URL does not end in .git. If the list contains exactly one entry and its url is a single word (no /, . or :), it is treated as a GitHub user or org name and expanded into all of that user/org's source (non-fork) repositories. Forks are always excluded; include_private and include_archived in defaults control whether private and archived repos are included. Private repos are listed via the token's own account endpoint, so when the single word names the user the token belongs to, their private repos are returned as expected. The expanded repos inherit the entry's token, destination and options from defaults.

Merge rules

  • A repository entry inherits every setting from defaults and overrides only the fields it sets explicitly.
  • destination.name defaults to the repository name taken from the source url (a trailing .git is stripped).
  • Unset option flags resolve to false/"" — there are no hidden built-in defaults. Set what you want migrated in defaults.
  • Unknown keys in the config are rejected.

License

This software is licensed under the EUPL-1.2 license. See the LICENSES/EUPL-1.2.txt file for the full license text.