Skip to content
5 min read

Migrate from GitHub to Forgejo

Forgejo includes a GitHub migrator, so moving off GitHub does not have to mean starting with an empty Git repository. Use Forgejo’s importer for each repository when you want code plus project history, or script the same move with fj when you are moving more than one repository.

This is a self-serve guide. If you want the destination to be a managed, single-tenant Forgejo instance instead of a server you operate yourself, you can do it on Fjord.

What Forgejo can import from GitHub

From the Forgejo web UI, create a new repository and choose the migration option instead of an empty repository. Select GitHub as the source and give Forgejo the repository URL.

For supported GitHub imports, Forgejo can bring over:

  • Git history, branches, and tags.
  • Issues and pull requests, including their discussion history.
  • Labels and milestones.
  • Releases.
  • Git LFS objects, when LFS migration is enabled and the source credentials can read them.

For a private GitHub repository, create a GitHub personal access token with the least read scope that can access the repository, paste it into the migration form, and revoke it after the import finishes. The migration runs server-side, so large repositories can take time.

Note

A raw git push --mirror only moves Git refs. It does not move issues, pull requests, labels, milestones, releases, or LFS objects. Use the Forgejo migrator when you need the project history, not just the code.

One repository from the web UI

Use the web migrator when you have one repository or a small number of repositories:

  1. Sign in to your Forgejo instance.
  2. Create a new repository and choose Migrate repository.
  3. Set the service to GitHub.
  4. Enter the GitHub clone URL.
  5. Add a read token if the repository is private or if you need metadata that requires authenticated API access.
  6. Enable the metadata you want to import, including issues, pull requests, releases, labels, milestones, and LFS.
  7. Start the migration and wait for Forgejo to finish the server-side import.

After it completes, clone the new Forgejo repository in a clean directory and check that branches, tags, issues, pull requests, releases, and LFS files are present before you archive or lock the GitHub source.

Bulk migration

Forgejo’s web UI is repository-by-repository. There is no web bulk-import button for moving an organization in one step. For batches, script the migration instead of clicking through every repository.

With the fj CLI, select your Fjord or Forgejo instance and run one migration per source repository:

fj instances use my-instance
fj repo mirror https://github.com/acme/api.git \
  --service github \
  --dest acme/api \
  --private \
  --auth-user <github-user> \
  --auth-pass <github-token>
fj repo mirror https://github.com/acme/web.git \
  --service github \
  --dest acme/web \
  --private \
  --auth-user <github-user> \
  --auth-pass <github-token>

For a larger move, keep a small text file of source URLs and loop over it from your shell, passing a short-lived token through your environment or secret store. Move repositories in waves so a failed import is easy to inspect and retry.

The repository migration runbook covers batching, mirror-then-switch cutovers, source-token hygiene, and verification for larger teams.

Mirror first or move once

Choose the migration mode based on how much coordination you need.

Use a one-time import when the GitHub repository can stop receiving writes while you move it. This is the simplest path: import once, verify the Forgejo copy, update remotes, and archive or lock the GitHub repository.

Use a pull mirror when you need a transition window. Forgejo can keep pulling from GitHub on a schedule while your team verifies the new home. When you are ready to cut over, freeze writes on GitHub, trigger a final mirror sync, turn the mirror into a normal repository, and have developers push to Forgejo.

With fj, add --mirror and an interval when you want a pull mirror:

fj repo mirror https://github.com/acme/api.git \
  --service github \
  --dest acme/api \
  --mirror \
  --interval 8h \
  --auth-user <github-user> \
  --auth-pass <github-token>

GitHub Actions on Forgejo Actions

Forgejo Actions uses the GitHub Actions workflow syntax. Workflow files under .github/workflows/ are discovered and run as-is by Forgejo Actions, so you do not need to rename them just to migrate.

Some teams optionally move workflows to .forgejo/workflows/ later to make the new host explicit. That is a cleanup choice, not a migration requirement.

Do check the parts that are not stored in the workflow file:

  • Recreate repository or organization secrets on Forgejo.
  • Recreate variables and environment protection rules you depend on.
  • Confirm any action references that point at github.com. If your runner cannot or should not reach GitHub, use Forgejo-hosted actions or Fjord’s drop-in Actions replacements where they fit.
  • Run at least one workflow on Forgejo before you turn off GitHub.

Update remotes and integrations

After the import is verified, move developer and automation traffic to Forgejo:

git remote set-url origin <forgejo-repo-url>
git fetch origin --prune

Then update webhooks, deploy keys, status checks, package publishing, Pages configuration, and any bots that still call GitHub APIs. Secrets and webhooks do not migrate automatically with the repository.

Verify before decommissioning GitHub

Do not archive the GitHub repository until the Forgejo copy is complete:

  • Branch and tag counts match.
  • Issues, pull requests, labels, milestones, and releases are present.
  • LFS files fetch from a fresh clone.
  • CI runs successfully on Forgejo Actions.
  • Developers can clone, push, and open a pull request on the new instance.
  • Old GitHub tokens used for migration have been revoked.

Do it on Fjord

Fjord gives you a managed, single-tenant Forgejo instance, managed Linux CI with optional dedicated runners, and nightly, encrypted, off-site backups with 90-day rolling retention. You still use Forgejo’s own migrator and the self-serve steps above, but the server operations are handled for you.

Start on a managed Forgejo instance

Contributors
  • Stephen Way