Migrate from GitHub to Forgejo: what moves, who does it, and how much effort
Git history and most collaboration metadata move from GitHub to Forgejo with documented commands, while GitHub Actions workflows and secrets need rework. If your renewal, licensing change, residency requirement or lock-in concern is pushing you toward a self-hosted forge, expect the repositories, issues, pull requests, releases, labels, milestones, comments and wikis to come across through dump-repo and restore-repo, and plan a separate track for CI and credentials. The Forgejo command-line documentation lists the selectable units, so run a trial export on one representative repository and check the restored issue numbers, comments and wiki pages before you schedule the full move.
In most organizations the platform or DevOps team runs the migration, because it owns the forge, the runners and the access model. An implementation partner usually adds value on scope, cutover sequencing and hardening: deciding which repositories move first, how to freeze pushes during the final sync, how branch protection and team permissions are rebuilt, and how backups and monitoring are set up on the new server. Ask any partner for a written scope that names the repositories, the metadata units in scope and the acceptance checks, since a fixed scope is what keeps effort predictable.
Effort depends mainly on the number of repositories, how many workflows they contain, and how many secrets and external integrations point at GitHub. Forgejo's documentation falls back to .github/workflows when .forgejo/workflows is absent, but it notes that migrated workflows will most likely need some minimal tweaking, and Actions secrets never export, so each one must be re-created by its owner. The Forgejo upgrade and release documentation also describes support windows you should weigh when choosing a version to standardize on. Confirm exact effort and timing with your own inventory of repositories and pipelines, not with generic estimates.
Which GitHub features map cleanly to Forgejo and which need rework
This table maps each GitHub feature to its Forgejo equivalent and marks it as clean, needs rework or gap. Read the migration column first, then check the notes on Actions, webhooks and app integrations, which need testing against the Forgejo version you run.
| Feature | Forgejo equivalent | Status | What to check |
|---|---|---|---|
| Repositories and Git history | Git repositories hosted in Forgejo | Clean | Mirror with all refs so branches and tags move unchanged. |
| Issues | Forgejo issues, carried by dump-repo | Clean | Confirm issue numbering and closed states after restore-repo. |
| Pull requests | Forgejo pull requests, carried by dump-repo | Clean | Review merged and closed PRs, plus any PR review comments. |
| Comments | Issue and PR comments, carried by dump-repo | Clean | Check that comment authors and timestamps appear as expected. |
| Labels and milestones | Forgejo labels and milestones, carried by dump-repo | Clean | Spot-check colors, descriptions and milestone due dates. |
| Releases and release assets | Forgejo releases and assets, carried by dump-repo | Clean | Confirm asset downloads work and large files were not truncated. |
| Wiki | Forgejo wiki, carried by dump-repo | Clean | Verify internal links, since wiki link paths can differ. |
| Actions workflows | Forgejo Actions, with fallback to .github/workflows | Needs rework | Forgejo Actions is not compatible with GitHub Actions. Expect to adjust runners, actions and syntax. |
| Actions secrets | Forgejo repository and organization secrets | Needs rework | Secrets do not export from GitHub. Re-create each one and record its owner. |
| Webhooks | Forgejo webhooks | Needs rework | Recreate endpoints and payload settings, then confirm behavior in the Forgejo documentation for your version. |
| Branch protection rules | Forgejo branch protection | Needs rework | Confirm required reviews, status checks and push rules match your policy in the Forgejo documentation for your version. |
| GitHub Apps and OAuth integrations | No direct equivalent in Forgejo | Gap | Identify each app, then find a replacement, a webhook-based integration or a custom service. Confirm with the Forgejo documentation. |
What data leaves GitHub and how to carry it over
Moving from GitHub to Forgejo is four separate jobs, not one export. Git history, repository metadata, Actions workflows and secrets each leave GitHub by a different route, and each needs its own check. The cards below cover what moves, what does not, and what must be rebuilt around the repositories.
Git history by clone or mirror
Commits, branches and tags move with a mirror clone of each repository, which is the most reliable part of the migration. Run the mirror against every branch and tag you intend to keep, then confirm commit counts and tag lists on both sides. Check the size of each repository early, because GitHub recommends keeping the .git folder under 10 GB and enforces a 100 MB file limit. Large binaries in history will need a separate plan, such as Git LFS or removal before the move.
Metadata with dump-repo and restore-repo
The Forgejo command-line tools export issues, pull requests, reviews, labels, milestones, releases, comments and the wiki from GitHub, then load them into Forgejo. Choose units explicitly so you do not carry data you do not need, and run a test dump on one repository first. Expect some drift in attribution and timestamps for imported comments, and confirm that pull request references still resolve after the restore.
Actions workflows through the fallback
Forgejo reads workflows from .forgejo/workflows and falls back to .github/workflows when that directory is missing, so existing files can run without being renamed first. Forgejo Actions is built to feel familiar to GitHub Actions users but is not compatible with it. Plan to review each workflow for marketplace actions, runner labels, event names and cache steps, and test them on a Forgejo runner before cutting over.
Secrets must be re-created by hand
GitHub Actions secrets and variables do not export, so every token, deploy key and cloud credential must be issued again in Forgejo. Inventory which workflows read which secrets before the cutover, rotate credentials that were shared widely, and record the new values in your secrets manager rather than in repository settings alone. Ask the team who owns each deploy key, since that owner is usually the person who must approve its replacement.
Integrations to rebuild
Webhooks, GitHub Apps and OAuth connections point at GitHub and stop working once repositories move. Rebuild the links to CI runners, container registries, chat notifications and deployment tools, and confirm that each one accepts events from the new forge. Build an inventory from the GitHub organization settings and from the deployment tools' configuration, since many of these connections were created by individuals and are not listed centrally.
API limits on bulk export
Scripted exports through the GitHub REST API are capped at 5,000 requests per hour for personal access tokens, so a large organization may need to run exports in batches over several hours. Use a dedicated token for the migration, schedule the largest repositories first, and log which items failed so a rerun picks them up. Confirm the token scopes you need before you start, because a failed export late in the window costs time you may not have.
The migration sequence from inventory to decommission
This sequence moves GitHub repositories and their collaboration metadata to Forgejo in controlled stages, so each repository reaches a verified state before GitHub access is removed. Each step closes with a named record that the next step depends on.
Inventory repositories, dependencies and integrations
Start by listing every repository in scope with its owner, size, default branch, open issues and pull requests, releases, wiki use and Actions workflows. Record every dependency on GitHub, including webhooks, GitHub Apps, OAuth applications, deploy keys, package registries, badges, bots and external CI systems that call GitHub APIs. Note which Actions secrets exist, since secret values never export and must be re-created in Forgejo. The output is an inventory register with one row per repository and one row per integration, reviewed by the repository owners. Confirm repository size limits and any files above GitHub's 100 MB file limit before the pilot, because large files need a decision on Git LFS or removal.
Pilot one repository with dump-repo and restore-repo
Choose a low-risk repository with issues, pull requests, labels, milestones and a wiki, then run Forgejo's dump-repo command against it with the unit selection that matches your inventory. Load the result into a test Forgejo instance with restore-repo, and compare counts of issues, pull requests, comments, releases, labels and milestones against GitHub. Check that attachments and wiki pages arrived and that authors and timestamps look right. The output is a pilot restore report listing what matched, what was missing and any manual fixes, which becomes the template for the rest of the migration. Agree the report with the repository owner before scaling up.
Adapt workflows and map secrets in the test instance
Forgejo falls back to .github/workflows when .forgejo/workflows is absent, so existing workflows may run without changes. Migrated workflows will most likely need minimal tweaks, because Forgejo Actions is designed to be familiar to GitHub Actions users but is not compatible with it. Move the workflows into .forgejo/workflows where you want Forgejo-specific behavior, check actions referenced by the workflows exist on your Forgejo runners, and assign runners to labels the jobs require. Re-create each secret manually in the Forgejo repository or organization settings, using the list from the inventory. The output is a workflow test log showing which jobs passed on Forgejo runners and a secrets checklist signed by the repository owner.
Run a parallel period with mirrored history
Keep GitHub as the system of record while teams work in both places. Mirror the Git history to Forgejo with a clone or mirror push, and schedule repeated runs of the export and restore steps for the metadata that changes, such as new issues and comments, so the two sides stay close. Compare branch heads, tag lists and open item counts on each sync, and record every difference. Confirm that webhooks and CI triggers fire only once, so builds and notifications are not duplicated. The output is a parallel run log showing the sync results and a list of open discrepancies with owners, which must reach zero before cutover.
Execute cutover with a freeze window
Announce a freeze window in which no one merges, opens or edits items on GitHub for the affected repositories. Run a final dump-repo export, restore it into Forgejo, and repeat the comparison from the parallel run. Then update remote URLs on developer machines and in build systems, move DNS or internal links that point to the old location, and enable the production Forgejo runners and webhooks. Confirm access for each team before lifting the freeze. The output is a cutover runbook with timestamps for each action, the names of the people who executed and verified each step, and a rollback path that states who decides to revert and how.
Verify production and decommission GitHub access
After a defined stabilization period agreed in advance, check that builds, deployments, package publishing and integrations work from Forgejo, and that teams can clone, push, review and file issues. Remove or disable GitHub webhooks, deploy keys, GitHub Apps and tokens, revoke personal access tokens used for migration, and set GitHub repositories to archived or read-only if you keep them for reference. Record the retention decision for GitHub data and where the exported archive is stored. The output is a signed-off decommission checklist covering each repository, each revoked credential and the owner who approved the change.
How to run GitHub and Forgejo side by side before cutover
Run GitHub as the system of record until cutover, and treat Forgejo as a rehearsal copy that is refreshed on a schedule. Git history is the part that can stay live: keep a mirror of each repository current so that every branch and tag is available on Forgejo before anyone depends on it. The metadata is different. Issues, pull requests, comments, labels, milestones, releases and the wiki come across through the dump-repo and restore-repo commands in the Forgejo command-line interface, and a restore is a snapshot of GitHub at the moment it ran. Each refresh overwrites the picture, so the team should record which export produced the copy that people are reviewing.
Decide, per repository, which platform accepts new pull requests and who can change that decision. Until the freeze, GitHub should keep accepting pull requests and issues, and Forgejo should be used for verification only. Assign one owner per repository for the switch, and make the owner responsible for telling contributors where to open work. Test workflows on Forgejo runners in parallel: the Forgejo documentation says Forgejo falls back to .github/workflows when .forgejo/workflows is absent, but migrated workflows will most likely need some tweaking, and Forgejo Actions is not compatible with GitHub Actions. Keep a list of failing jobs, and confirm which secrets must be re-created by hand, since Actions secrets do not export.
Schedule the final metadata export inside the freeze window, after GitHub stops accepting new pull requests and issues for the repository. Any export taken earlier will miss comments and reviews added since, so the freeze, the final dump-repo run, the restore-repo run and the switch of contributor links should happen in that order. Check each restored repository against GitHub for issue counts, pull request states and attachments that did not carry over, and record the gaps. Before the freeze begins, confirm with your own platform team the export account, the token scopes and any API limits that will slow a large repository, because the rate limits for hosted services apply to bulk exports as well.
What drives migration cost and duration, and how to keep each down
This table lists the factors that change the effort and cost of moving GitHub repositories to Forgejo, with how each one moves the total and what to do about it. Read it as a checklist for scoping and for the questions to put in a written quote.
| Driver | Why it changes cost or effort | How to keep it down |
|---|---|---|
| Number of repositories | Each repository needs its own dump, restore, permission mapping and verification, so effort grows with count even when repositories are small. | Group repositories by owner and purpose, migrate low-risk ones first, and confirm in the quote whether the scope is a fixed list or open-ended. |
| Total .git size | GitHub recommends keeping a repository's .git folder under 10 GB, and larger histories take longer to clone, mirror and restore. | Identify oversized repositories early, clean up binary history where the team agrees, and plan separate transfer windows for the largest ones. |
| Volume of issues, pull requests and comments | The dump-repo command exports issues, pull requests, comments and reviews, so large trackers lengthen export and restore and need more checking. | Agree which closed history must move, archive the rest in read-only form, and sample restored items against the source. |
| Reliance on GitHub Actions and marketplace actions | Forgejo Actions is not compatible with GitHub Actions. Forgejo falls back to .github/workflows, but migrated workflows will most likely need some minimal tweaking, and each third-party action must be checked for support on Forgejo runners. | Inventory every workflow and action reference, rank them by business impact, and test the top workflows on a Forgejo runner before cutover. |
| Secrets and integrations | Actions secrets do not export, so each secret must be re-created by its owner. Webhooks, deploy keys, GitHub Apps and external services must be repointed. | Build a secrets register with owners and rotation status, and re-issue credentials during the pilot rather than at cutover day. |
| Hardening and backup design | The server, TLS, authentication, backup target and restore testing are sized by data sensitivity and availability needs, not by repository count. | Reuse a standard server template, define backup frequency and retention in writing, and include a restore test in the scope. |
| Staff time for testing and cutover | Developers must verify clones, branch protection, reviews and pipelines, and platform staff must run the cutover and rollback plan. This is usually the largest one-time item. | Run a pilot with one or two teams, write acceptance checks per repository, and schedule cutover outside release freezes. |
| One-time costs | Assessment, migration scripting, workflow conversion, secret re-creation, testing and cutover are paid once, whether by internal staff or a services firm. | Ask for each activity as a separate line with a named owner and a fixed deliverable. |
| Recurring costs | Server or cloud capacity, storage, backups, Forgejo upgrades, security patching and any support contract continue after go-live, and staff time for operations is recurring too. | Ask for the upgrade and patch cadence, the support model and a monthly run cost estimate that names each component. |
| What to ask for in a written quote | A quote is comparable only when scope, exclusions and assumptions are explicit. | Request the repository inventory assumptions, the number of workflows and secrets in scope, test and rollback criteria, backup and restore testing, handover documents and the upgrade path to later Forgejo releases, including any upgrade from Gitea. |
What usually goes wrong in a GitHub to Forgejo move
Most failed migrations break at the edges rather than in the Git history itself. The risks below cover workflows, secrets, integrations, file sizes, data freshness and support timing, and each one has a check to run before cutover.
Assuming workflows run unchanged
Forgejo Actions is designed to be familiar to GitHub Actions users but is not compatible with it. Forgejo falls back to .github/workflows when .forgejo/workflows is absent, but migrated workflows will most likely need some minimal tweaking. Before cutover, run each workflow on a test runner, check actions referenced from the marketplace, and confirm that runner labels match the jobs that expect them.
Losing secrets that never export
Actions secrets are not included in a repository dump, so every secret used by a pipeline, deploy job or registry login must be re-created in Forgejo by hand. Inventory the secret names from each workflow, assign owners who can supply the values, and rotate any credential whose value cannot be confirmed. Do not copy secret values through a chat tool or spreadsheet.
Broken webhooks and deploy keys
Webhooks, deploy keys and integrations tied to GitHub will stop firing once the repository moves, and some deploy keys may have been registered only on GitHub. List every hook in the repository settings, recreate it against the Forgejo URL, and send a test event. Confirm that each external system accepts the new endpoint and that deploy keys are added to Forgejo with the same read or write scope.
Large files over GitHub limits
GitHub enforces a 100 MB file limit and a 2 GB push limit, and recommends keeping a repository's .git folder under 10 GB. Repositories that passed those limits on GitHub, often through Git LFS or committed binaries, may carry objects that are slow to move or that the target server rejects. Measure the repository size with git count-objects before the move, confirm LFS objects are copied, and plan storage on the Forgejo server accordingly.
Stale metadata after a snapshot
A dump-repo export is a point-in-time copy, so issues, comments, labels and pull request reviews created on GitHub after the export will not appear in Forgejo. Freeze new activity on the source repository, or schedule a final export and restore just before cutover. Then compare issue and pull request counts between the two systems and record the cutover time in the team's change log.
Unclear Forgejo version support windows
Stable Forgejo releases receive full support for three months plus a two-week window, while LTS releases receive critical bugfixes and security support for one year and three months. Choosing a release without checking its end date can leave the server unpatched soon after go-live. Pick an LTS release for production, record its support end date, and set a calendar reminder for the upgrade plan. Forgejo v15 is the LTS release supported until July 15, 2027.
How the migration changes by team size and starting point
A small team with a handful of repositories and simple CI usually has a short inventory and few moving parts. The work is mostly running the dump and restore for each repository, checking that issues, pull requests and wikis arrived intact, and rewriting a few workflow files. Most of the effort sits in deciding who owns the new server and how it gets patched.
- Inventory: List each repository, its default branch, open pull requests and whether anyone still uses its wiki or releases.
- Workflows: Forgejo falls back to
.github/workflowswhen.forgejo/workflowsis absent, but migrated workflows will most likely need some minimal tweaking, so test them on a branch first. - Secrets: Plan to re-create Actions secrets by hand in Forgejo, since they do not export.
- Operations: Assign one owner for updates, backups and the Forgejo runner, because a small team rarely has a spare administrator.
- Cutover: A single weekend window is often enough when the repository count is low, though this depends on your own environment.
Before starting, confirm the release line you will install and its support window in the Forgejo releases and upgrade documentation.
A large organization with many repositories, teams and GitHub Apps needs a migration plan that is sequenced by team and dependency rather than by repository. The dump and restore commands work one repository at a time, so the bulk of the work is building a list, batching it and tracking which repositories have been verified. Integrations are usually the largest unknown.
- Batching: Group repositories by owning team and by dependency so that linked services move together.
- Integrations: Map every GitHub App, webhook and bot account, since none of them move with the repositories and each needs a Forgejo replacement or a rewire.
- Access model: Rebuild teams, permissions and branch protection rules in Forgejo before migrated users start working.
- Pilot: Run a pilot batch with one or two teams to measure the verification effort before scheduling the rest.
- Rate limits: Plan exports around the API rate limits of the source platform, such as GitHub's 5,000 REST requests per hour for personal access tokens.
Ask your implementation partner to show the written inventory and the batch plan as part of the scope.
Teams on GitHub Enterprise Server or on GitHub Enterprise Cloud with data residency are often moving for hosting control, not only for cost. The starting point affects where the data is exported to and who approves the change. Before any repository moves, confirm whether the organization's requirement is about location, operator control or both, since a self-hosted Forgejo answers the second and changes the first.
- Requirements: Write down the residency and operator control requirements, and check them against your own environment and any contractual terms.
- Export path: Confirm how the data will leave the current platform and where the export files will be stored during the move.
- Approvals: Involve security, compliance and the data owners early, because the export contains issues, comments and attachments that may hold personal data.
- Parallel running: Plan a period where the source and target both exist, and decide which system is authoritative for each repository.
- Support: Check the support model for the self-managed edition you are leaving, since the replacement is a different software and support arrangement.
Confirm the data handling terms with your legal and compliance team before the first export.
Teams already running Gitea have an advantage, because Forgejo documents transparent upgrades from Gitea installations up to Gitea v1.22. That path is an in-place upgrade of the existing installation rather than a repository-by-repository move, so the scope is about the server, the database and the version path. Teams on a Gitea release later than v1.22 should confirm with the Forgejo upgrade documentation whether a different route applies.
- Version check: Confirm the exact Gitea version in use and whether it is at or below v1.22.
- Upgrade order: Forgejo documents a two-step path, first to Forgejo v10.0.x and then to a later Forgejo version, so plan both steps and their rollback points.
- Backups: Take and test a full backup of the database and repository data before each step.
- Actions: Check which Gitea Actions workflows and runners are in use, since runner configuration may change during the upgrade.
- Testing: Verify repositories, webhooks and user logins on a staging copy before the production upgrade.
Before starting, confirm the current Gitea version and the upgrade steps against the Forgejo upgrade guide.
Questions buyers ask before moving from GitHub to Forgejo
What does a migration from GitHub to Forgejo cost, and what drives it?
The software itself is free to download under GPL-3.0-or-later from v9.0 onward, so the cost is in the work and the infrastructure around it. Expect one-time costs for planning, the migration run, Actions rework and cutover, plus recurring costs for servers, storage, backups, patching, upgrades and staff time. The main drivers are the number of repositories, how much metadata (issues, pull requests, releases, wikis) you need to keep, how many workflows and secrets depend on GitHub Actions, and whether you need data residency or high availability. Ask any provider for a written scope that lists these items separately so you can compare quotes on the same basis.
How long does a GitHub to Forgejo migration usually take?
The duration depends on the scope rather than on the software. The biggest factors are the number of repositories, the volume of issues, pull requests and releases per repository, the size of the repositories themselves, and how many CI workflows need changes. Hosted platforms also impose API rate limits on bulk exports, and GitHub's REST limit of 5,000 requests per hour for personal access tokens means large exports can take time to run. Confirm a schedule with your provider or internal team against a pilot batch of repositories before committing to a cutover date.
What does our internal team need to provide for the migration?
You need named owners who can approve scope, a GitHub token with access to the repositories being exported, a target Forgejo instance with storage and backup in place, and a list of teams, users and access rules to map. Engineering leads should identify which repositories are active, which workflows and secrets they depend on, and which external systems post to GitHub webhooks. Security and compliance staff should confirm where the data may be stored and who may administer the instance. Ask whether your provider expects these inputs in writing before work starts.
Can our own engineers run the migration with the documented commands?
Yes, for many teams the documented route is straightforward. Forgejo's command-line interface provides dump-repo, which exports a repository from GitHub with selectable units such as issues, labels, releases, milestones, pull requests, comments and wiki, and restore-repo, which loads the dump into Forgejo. The harder parts are repeatable batch runs across many repositories, handling exceptions, mapping users and permissions, and validating the results. Self-run teams should test on a few repositories, check the restored data against GitHub, and decide who signs off. An outside team can take on the parts that are not worth your staff's time.
How do Forgejo's license and LTS support windows affect planning?
Forgejo's license is GPL-3.0-or-later from v9.0, with earlier versions under MIT, so confirm with your legal team which terms apply to the version you deploy. For support, stable releases get full support for three months plus a two-week window, while LTS releases receive critical bugfixes and security support for one year and three months. Forgejo v15 is the LTS release supported until July 15, 2027, and v17.0.0 is supported until January 28, 2027. Plan your upgrade path around the LTS you choose, and schedule upgrades before the end of each support window.
How are GitHub Actions workflows and secrets handled after the move?
Forgejo Actions is designed to be familiar to GitHub Actions users but is not compatible with it. Forgejo falls back to .github/workflows when .forgejo/workflows is absent, so many workflows run with minimal tweaks, though Forgejo's documentation says migrated workflows will most likely need some adjustment. Actions secrets do not export from GitHub, so every secret must be re-created in Forgejo by its owner and validated against a test run. Budget time for runner setup, testing each pipeline, and replacing any third-party actions that do not behave the same way.
Does Forgejo keep our data in the region we choose?
Self-hosting means the location of your data is determined by where you install Forgejo, such as your own data center or a cloud region you select. Hosted GitHub options vary: GitHub Enterprise Cloud with data residency offers EU, Australia, US and Japan regions, and Azure DevOps stores customer data in the geography chosen for the organization. Your compliance team should confirm how backups, logs and runner caches are stored and replicated in your own environment, since those can sit outside the primary instance.
How DeployOpen scopes and runs a GitHub to Forgejo migration
DeployOpen is a Chainscore Labs company that plans, implements, customizes, integrates, hardens, backs up, upgrades, documents and supports self-hosted open-source platforms inside the client's own cloud accounts, data centers or air-gapped networks. A GitHub to Forgejo move is scoped in writing first, then built, tested and handed over with documentation for the team that will run it.
How we scope
- Inventory repositories, issues, pull requests, releases, wikis and Actions workflows that must move, and note which ones can be archived instead.
- Agree in writing which Forgejo dump-repo units are in scope, such as issues, labels, milestones, comments and wikis.
- Record where Forgejo will run, which data location applies and who owns the GitHub token used for export.
How we build
- Stand up the Forgejo instance in your environment, with the configuration, storage and backup design agreed in the scope.
- Run test migrations of sample repositories with dump-repo and restore-repo, and compare issues, pull requests and labels against the source.
- Adapt migrated workflows from .github/workflows to Forgejo Actions, then re-create secrets in Forgejo and verify each pipeline runs.
How we hand over
- Deliver runbooks covering the cutover order, repository mapping, user access and rollback steps for the migration.
- Document the Forgejo version in use, its upgrade path and how to confirm the support window for that release.
- Walk your administrators and developers through the new repositories, pull request flow and Actions runners before cutover closes.
How we support
- Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
- Ongoing support, upgrades and continuous testing are available as a retainer after handover.
- Ask for the written scope to list who is responsible for runners, backups and Forgejo upgrades after go-live.

