[READ-ONLY] Mirror of https://github.com/mrgnw/migrate-github-to-codeberg. Rust TUI and shell script for migrating GitHub repositories to Codeberg while preserving GitHub remotes.
0

Configure Feed

Select the types of activity you want to include in your feed.

Rust 94.3%
Shell 5.7%
10 1 0

Clone this repository

https://git.vm.fail/xcc.es/migrate-github-to-codeberg https://git.vm.fail/did:plc:urmf7oo2v5kcayj342sth2z6
ssh://git@knot1.tangled.sh:2222/xcc.es/migrate-github-to-codeberg ssh://git@knot1.tangled.sh:2222/did:plc:urmf7oo2v5kcayj342sth2z6

For self-hosted knots, clone URLs may differ based on your setup.


README.org
#+TITLE: GitHub to Codeberg Migration Script
#+AUTHOR: Rahul Martim Juliato
#+EMAIL: rahul.juliato@gmail.com
#+OPTIONS: toc:nil

#+begin_quote
[!NOTE]
The Rust TUI addition was built with heavy LLM assistance and should be
considered proof-of-concept. Contributions are welcome, but I can't
guarantee the accuracy of the code or that I will continue to maintain
it. If there are any mistakes in attribution or anything else, please
let me know.
#+end_quote

* Overview

This script automates the migration of GitHub repositories to
Codeberg. It allows you to seamlessly transfer your projects from
GitHub to Codeberg while preserving their metadata, such as
descriptions and access permissions.

The Rust TUI provides a two-step workflow for users who want to copy
repositories to Codeberg while keeping GitHub remotes available locally.
It never removes code from GitHub.

* Features

- Migrate all or selected repositories from GitHub to Codeberg.
- Customizable prefix for repository descriptions.
- Customizable filter for repository owners.
- Supports pagination for fetching large numbers of repositories.
- Error handling for repository migration failures.

* Limitations

Due to the complex nature of both Github and Codeberg apis, it was a
design choice for this script to omit several features like:
- distinction between forks and original repositories
- wiki
- pull requests
- avatars for projects

...and so on. Please modify this script to your own needs.

* Usage

** Rust TUI

Set the API tokens in your shell. Usernames are optional when the
tokens can be used to detect them.

#+BEGIN_SRC sh
export GITHUB_TOKEN=
export CODEBERG_TOKEN=
export GITHUB_USERNAME=
export CODEBERG_USERNAME=
cargo run -- --check --dir "$HOME/dev"
cargo run -- --export inventory.json --dir "$HOME/dev"
cargo run -- --dir "$HOME/dev"
#+END_SRC

The TUI shows one unified table. Rows are merged from local Git repos
under the selected directory, GitHub repositories visible to the token,
and Codeberg repositories visible to the token. The ~⌂~, ~◆~, and ~●~
columns show whether a repo exists locally, on GitHub, and on Codeberg.
Local paths are shown relative to the selected directory, and top-level
local repos do not repeat the directory path.

If a required value is missing, the TUI opens a small configuration
form for the GitHub user, GitHub token, Codeberg user, and Codeberg
token. Press ~e~ to reopen it later, or click ~GitHub [user]~ or
~Codeberg [user]~ in the header to edit the corresponding owner.
Press ~Tab~ to move between fields and ~Enter~ to save. Values are kept
in memory for the current run.

Press ~Enter~ or ~m~ to process selected rows. If a selected repo is not
on Codeberg yet, the TUI starts the Codeberg copy first. For local rows,
the origin update is deferred until the copy succeeds or Codeberg
already reports that the repo exists. It will not set a local ~origin~
to a Codeberg URL that is not known to exist.

Other keys: ~Space~ toggles one repo, ~v~ sets a range anchor, ~V~
toggles the anchor-to-cursor range, ~a~ toggles all repos, ~s~ cycles
sort order (~local first~, ~recent~, ~name asc~, ~name desc~), ~k~ runs
the non-mutating access check, ~r~ reloads local/API state, and ~q~
quits.

If the GitHub API listing does not include a local repo's GitHub
remote, the row is actionable only when the remote owner matches your
GitHub username. Remotes owned by someone else are marked for review
instead of copied automatically.

Local repos without a GitHub remote can be selected too. The TUI
creates a private empty Codeberg repository with the local directory
name, adds Codeberg as ~origin~ when there is no conflicting origin, and
pushes local branches and tags. Codeberg push-to-create is disabled, so
the repository is created through the API before Git pushes.

Rows with an ~upstream~ remote remain actionable, but are flagged as
~upstream remote~ so forks and vendored clones are easier to review.
Extra remotes are not removed.

The ~--export~ command writes a JSON inventory with the same rows used
by the TUI, plus remotes, local paths, GitHub metadata, Codeberg target
URLs, recommendations, risk flags, and load messages. Use it to review
ambiguous repos before starting migration:

#+BEGIN_SRC sh
cargo run -- --export inventory.json --dir "$HOME/dev"
#+END_SRC

The ~--check~ command and ~k~ key verify the non-mutating prerequisites:
GitHub token presence, GitHub identity, GitHub repository listing,
Codeberg token presence, Codeberg identity, Codeberg repository
listing, and local directory scanning. They do not call the Codeberg
migration endpoint because that endpoint creates remote state.

Optional environment variables:

- ~MIGRATE_PROJECT_DIR~: default directory when ~--dir~ is omitted.
- ~MIGRATE_EXCLUDE~: comma-separated relative path prefixes to skip
  during local scanning. The CLI also accepts repeated ~--exclude~
  flags.
- ~MIGRATE_CONCURRENCY~: copy concurrency, from 1 to 8. Default: 4.
- ~DESCRIPTION_PREFIX~: prefix for migrated Codeberg descriptions.
- ~CODEBERG_BASE_URL~: Forgejo-compatible base URL. Default:
  ~https://codeberg.org~.

** Configure User Settings
   - Open the script file (~migrate_github_to_codeberg.sh~) in a text editor.
   - Update the user configuration section with your GitHub and
     Codeberg credentials.
   - Optionally, define the repositories you want to migrate by adding
     their names to the ~REPOSITORIES~ array.
   - Optionally, define the owners of the repositories that you want to
     migrate by adding their usernames to the ~OWNERS~ array.

** Install Dependencies
   - Ensure that ~curl~ and ~jq~ are installed on your system.
     - On Debian/Ubuntu: ~sudo apt install curl jq~
     - On macOS with Homebrew: ~brew install curl jq~

** Run the Script
   - Execute the script by running ~./migrate_repositories.sh~ in your terminal.
   - Follow the on-screen instructions to proceed with the migration.
   - Press ENTER to start the migration process.

** Monitor Progress
   - The script will display information about the migration progress,
     including successful migrations and any errors encountered.

** Review Results
   - Once the migration is complete, review the results to ensure all
     desired repositories have been migrated successfully.

* Requirements

- Bash shell
- curl
- jq (JSON processor)
- Rust 1.93+ for the TUI


* Screenshots (in text mode)

#+BEGIN_SRC txt
    ----------------------------------------------
    Welcome to Github to Codeberg Migration Script
    ----------------------------------------------

    User on Github          : LionyxML
    User on Codeberg        : LionyxML
    Using description prefix: [MIRROR]
    Migrating repos owned by: all users
    Migrating repo          : aa
    Migrating repo          : dotfiles
    Migrating repo          : flycheck
    Migrating repo          : my_emacs_config

    If you wish to change this, abort and change this script.



    Press ENTER to continue, C-c to abort.


>>> Working...
>>> Migrating: aa... Error! Already exists on Codeberg.
>>> Migrating: flycheck... Success!
>>> Migration complete!
#+END_SRC


#+BEGIN_SRC txt
    ----------------------------------------------
    Welcome to Github to Codeberg Migration Script
    ----------------------------------------------

    User on Github          : LionyxML
    User on Codeberg        : LionyxML
    Using description prefix: [MIRROR]
    Migrating repos owned by: LionyxML
    Migrating repo          : all

    If you wish to change this, abort and change this script.



    Press ENTER to continue, C-c to abort.


>>> Working...
>>> Migrating: 100_computer_science_concepts... Error! Already exists on Codeberg.
>>> Migrating: 10_design_patterns... Error! Already exists on Codeberg.
>>> Migrating: aa... Error! Already exists on Codeberg.

#+END_SRC

* License

This project is licensed under [[file:LICENSE][GPL-3.0-only]].