Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
213 changes: 213 additions & 0 deletions content/blog/2025-11-07-github-and-away/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
---
title: Code hosting options beyond GitHub
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style Guide and (Ahem!) the author's checklist

Suggested change
title: Code hosting options beyond GitHub
title: Code Hosting Options Beyond GitHub

author:
- Mark Padgham
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@noamross needs to be here somewhere, author or editor? If you added content, I'd say author.

editor:
date: '2025-11-07'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to update the date here and in the folder when we have a new date for publication.

slug: beyond-github
description: How to manage and mirror code repositories across different platforms.
output: hugodown::md_document
tags:
- tech notes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can add some more tags! What do you think about...

Suggested change
- tech notes
- tech notes
- github
- maintenance
- help
- infrastructure
- git

params:
doi: "10.59350/bhr5x-d3429"
editor:
- Maëlle Salmon
- Adam Sparks
- Eric Scott
- Doug Kelkhoff
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Doug Kelkhoff
- Doug Kelkhoff
- Steffi LaZerte

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doug needs an author file

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just dropping in my info here:

---
name: Doug Kelkhoff
mastodon: https://fosstodon.org/@dgkf
bio: Research software engineer in healthcare. Chair of the R Validation Hub, an R Consortium Working Group.
github: dgkf
gitlab: dgkf
codeberg: dgkf
orcid: 0009-0003-7845-4061
---

---

rOpenSci makes heavy use of GitHub for our projects and services, including [software peer-review](https://github.com/ropensci/software-review/issues?q=sort%3Aupdated-desc%20is%3Aissue%20state%3Aclosed).
GitHub is by far the most widely used git or code-hosting platform, and the combination of its popularity and freemium services have made it central to open-source and R communities.
However, for a variety of reasons, some of our community members or potential members may prefer or need to use other platforms.
These reasons may include concerns about privacy, including [identifying information required for age verification in some jurisdictions](https://www.abc.net.au/news/2025-09-24/digital-dilemna-social-media-age-ban-platforms/105807302). Other reasons include a desire to support platforms with different ownership or business models, based in other countries, or supprting alternatives to avoid the risk of hegemony.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this section, it's absolutely needed and helpful especially for people like me that might have a hazy idea but would like more.

Suggested change
These reasons may include concerns about privacy, including [identifying information required for age verification in some jurisdictions](https://www.abc.net.au/news/2025-09-24/digital-dilemna-social-media-age-ban-platforms/105807302). Other reasons include a desire to support platforms with different ownership or business models, based in other countries, or supprting alternatives to avoid the risk of hegemony.
These reasons may include concerns about privacy, including [identifying information required for age verification in some jurisdictions](https://www.abc.net.au/news/2025-09-24/digital-dilemna-social-media-age-ban-platforms/105807302). Other reasons include a desire to support platforms with different ownership or business models, based in other countries, or supporting alternatives to avoid the risk of hegemony.


GitHub remains our primary code platform and we have no immediate plans to migrate, but we are keenly aware of the trade-offs our community is considering and that they vary from member to member.
We want to provide opportunities to help users not using GitHub to participate in rOpenSci activities, and we also to continually explore alternative platforms and models for the future.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
We want to provide opportunities to help users not using GitHub to participate in rOpenSci activities, and we also to continually explore alternative platforms and models for the future.
We want to provide opportunities to help users not using GitHub to participate in rOpenSci activities, and we also want to continually explore alternative platforms and models for the future.


In this post, we describe one approach rOpenSci members can use alternative platforms while still staying connected to rOpenSci operations on GitHub. This is most applicable to current or future developers of rOpenSci peer-reviewed packages, but we hope also serves as a useful guide for those testing approaches to managing code across multiple platforms more generally.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this post, we describe one approach rOpenSci members can use alternative platforms while still staying connected to rOpenSci operations on GitHub. This is most applicable to current or future developers of rOpenSci peer-reviewed packages, but we hope also serves as a useful guide for those testing approaches to managing code across multiple platforms more generally.
In this post, we describe one approach which allows rOpenSci members to use alternative platforms while still staying connected to rOpenSci operations on GitHub. This is most applicable to current or future developers of rOpenSci peer-reviewed packages, but we hope also serves as a useful guide for those testing approaches for managing code across multiple platforms more generally.


## Code (still) needs a single home
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a bit more detail as to what you're going to guide the readers through might be helpful.

Suggested change
## Code (still) needs a single home
This approach involves migrating from GitHub to another platform followed by setting up a mirror to GitHub. We'll start by exploring what this means and will end with some guidance on setting up multiple mirrors and some words of warning.
## Some background
### Code (still) needs a primary home


All platforms described here are based on [Git](https://git-scm.com/), which is generally used in a centralized way, through associating code with a single, main repository to which changes can be _pushed_, or from which changes can be _pulled_.
This kind of workflow assumes a single connection between code on your local machine and this single main version.
To keeps things simple, this post will therefore presume that every repository maintains a single, primary remote on one platform, with other platforms hosting or "mirroring" copies of the code.

## Mirroring on other platforms
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Mirroring on other platforms
### Mirroring on other platforms


Different remote instances of a Git repository are often referred to as "mirrors". Here "mirror" refers to copies of code on any platforms other than the primary remote.
Most examples presume GitHub to be the primary remote, because rOpenSci operations are built around that presumption, but any platform can serve as a primary remote location, with GitHub, and any number of other platforms then being mirrors.
"Alternative locations" just implies any additional mirror locations other than the primary remote.

Code mirrors are only ever updated through `git push` events from local versions, or from other `git` events on the primary remote.
Change events originating on the primary remote are generally incorporated in a local version via `git pull`, and then pushed out to all mirrored versions.
A `git pull` command should only ever be applied to the primary remote version, and never to any alternative mirror versions.
In this diagram, the large yellow arrow represents the only connection where both `push` and `pull` events are allowed.
All other arrows are `push` events only.
Comment on lines +46 to +47
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With these edits I don't think you need alt text in the image (i.e. use alt = "")

Suggested change
In this diagram, the large yellow arrow represents the only connection where both `push` and `pull` events are allowed.
All other arrows are `push` events only.
In this diagram, the large yellow arrow between the primary remote and local represents the only connection where both `push` and `pull` events are allowed.
All other arrows between mirrors, primary remote and local are `push` events only.


![](./local-remote.png)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove duplicated image?

Suggested change
![](./local-remote.png)


{{< figure src = "local-remote.png" alt = "Git interaction directions between local and remote repositories." class = "pull-left" caption = "Git interaction directions between local and remote repositories.">}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{{< figure src = "local-remote.png" alt = "Git interaction directions between local and remote repositories." class = "pull-left" caption = "Git interaction directions between local and remote repositories.">}}
{{< figure src = "local-remote.png" alt = "" class = "pull-left" caption = "Git interaction directions between local and remote repositories.">}}


### Mirroring on Codeberg or GitLab
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Mirroring on Codeberg or GitLab
## Migrating to Codeberg or GitLab


The easiest platforms on which to mirror your code are currently [Codeberg](https://codeberg.org) and [GitLab](https://gitlab.com), both of which have inbuilt options to mirror repositories directly from a large number of other platforms, including GitHub.
Both of these platforms can also mirror additional information including issues, issue labels, pull requests, and releases.
Comment on lines +55 to +56
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The easiest platforms on which to mirror your code are currently [Codeberg](https://codeberg.org) and [GitLab](https://gitlab.com), both of which have inbuilt options to mirror repositories directly from a large number of other platforms, including GitHub.
Both of these platforms can also mirror additional information including issues, issue labels, pull requests, and releases.
Let's get started! The first step of setting up your repository on a non-GitHub platform with a mirror to GitHub is migrating from GitHub to this new platform.
The easiest platforms to migrate to are currently [Codeberg](https://codeberg.org) and [GitLab](https://gitlab.com), both of which have inbuilt options to migrate repositories directly from a large number of other platforms, including GitHub.
Both of these platforms can also migrate additional information including issues, issue labels, pull requests, and releases.

There are some limitations. For instance, GitHub's auto-links within issues and pull requests may be lost.

To mirror a repo on Codeberg, click the large "+" button on the top right of the main menu bar, and select "New migration", like this:

![](codeberg-new-migration.png)
Comment on lines +59 to +61
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To mirror a repo on Codeberg, click the large "+" button on the top right of the main menu bar, and select "New migration", like this:
![](codeberg-new-migration.png)
To migrate a repo to Codeberg, click the large "+" button on the top right of the main menu bar, and select "New migration".


{{< figure src = "codeberg-new-migration.png" alt = "Codeberg new migration button." class = "pull-left" caption = "Codeberg new repository migration button.">}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{{< figure src = "codeberg-new-migration.png" alt = "Codeberg new migration button." class = "pull-left" caption = "Codeberg new repository migration button.">}}
{{< figure src = "codeberg-new-migration.png" alt = "" class = "pull-left" caption = "Codeberg new repository migration button.">}}


That will then open up the following grid of options from where you want to mirror your repository:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
That will then open up the following grid of options from where you want to mirror your repository:
That will then open up the following grid of options from where you want to migrate your repository:


![](codeberg-migration-options.png)

{{< figure src = "codeberg-migration-options.png" alt = "Codeberg repository migration options." class = "pull-left" caption = "Codeberg repository migration options.">}}
Comment on lines +67 to +69
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
![](codeberg-migration-options.png)
{{< figure src = "codeberg-migration-options.png" alt = "Codeberg repository migration options." class = "pull-left" caption = "Codeberg repository migration options.">}}
{{< figure src = "codeberg-migration-options.png" alt = "Codeberg repository migration options shown as icons including Git, GitHub, GitLab, Forgejo, Gitea, Gogs, OneDev, and GitBucket" class = "pull-left" caption = "Codeberg repository migration options.">}}```


To migrate from GitHub, click the symbol to open a migration to fill in some details, where you can also paste a GitHub token into "access token", and mirror almost all other aspects, including issues, pull requests, and releases.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorporate a bit from the transferring issues section so we can reduce duplication

Suggested change
To migrate from GitHub, click the symbol to open a migration to fill in some details, where you can also paste a GitHub token into "access token", and mirror almost all other aspects, including issues, pull requests, and releases.
To migrate from GitHub, click the symbol to open a migration to fill in some details, where you can also paste a GitHub token into "access token" (ensuring that it has at least read access to all aspects you want transferred), and migrate almost all other aspects, including issues, pull requests, and releases.

Note that the migration process may take 10 minutes or more.

On GitLab, the equivalent "+" button is on the top left, where "_New project/repository_" should be clicked:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
On GitLab, the equivalent "+" button is on the top left, where "_New project/repository_" should be clicked:
On GitLab, the equivalent "+" button is on the top left, where "_New project/repository_" should be clicked.


{{< figure src = "gitlab-new.png" alt = "GitLab new repository button." class = "pull-left" caption = "GitLab new repository button.">}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{{< figure src = "gitlab-new.png" alt = "GitLab new repository button." class = "pull-left" caption = "GitLab new repository button.">}}
{{< figure src = "gitlab-new.png" alt = "" class = "pull-left" caption = "GitLab new repository button.">}}


![](gitlab-new.png)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
![](gitlab-new.png)


That will lead to the following options, in which "Import project" should be clicked.

![](gitlab-import.png)

{{< figure src = "gitlab-import.png" alt = "GitLab repository import options." class = "pull-left" caption = "GitLab repository import options.">}}
Comment on lines +82 to +84
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
![](gitlab-import.png)
{{< figure src = "gitlab-import.png" alt = "GitLab repository import options." class = "pull-left" caption = "GitLab repository import options.">}}
{{< figure src = "gitlab-import.png" alt = "GitLab repository import options: Create blank project; Create from template; Import project; Run CI/CD for external repository." class = "pull-left" caption = "GitLab repository import options.">}}


That then leads to a list of platforms from which you can import projects, including code, issues, pull requests, releases, and other information.

Comment on lines +86 to +87
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorporate comments from the Transferring issues section to avoid repitition

Suggested change
That then leads to a list of platforms from which you can import projects, including code, issues, pull requests, releases, and other information.
That then leads to a list of platforms from which you can import projects, including code, issues, pull requests, releases, and other information.
GitLab transfers issues, pull requests, tags, and releases by default, with even more possible through provision of a GitHub access token.
As with Codeberg, this transfer can take some time (10-20 minutes or more).

### Mirroring elsewhere

No other platforms currently offer the one-click mirror functionality of Codeberg or GitLab.
To mirror in all other cases, you'll need to:

1. Create a new repository on the desired platform.
2. Set a `git remote` URL to the new destination.
3. `git push` to new remote.

The [git remote web page](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) provides more detail on working with remotes.
Comment on lines +88 to +97
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to after the Transferring issues

Suggested change
### Mirroring elsewhere
No other platforms currently offer the one-click mirror functionality of Codeberg or GitLab.
To mirror in all other cases, you'll need to:
1. Create a new repository on the desired platform.
2. Set a `git remote` URL to the new destination.
3. `git push` to new remote.
The [git remote web page](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) provides more detail on working with remotes.


## Transferring issues

Issues, pull requests, and other information on GitHub can be transferred both to Codeberg and GitLab, but only when a repository is first mirrored.
We are not currently aware of any platforms other these two which offer inbuilt ability to import additional information on issues and pull requests, although other people have implemented things such as [issue mirroring from GitHub to sourcehut](https://github.com/marketplace/actions/sourcehut-issue-maker).

Both Codeberg and GitLab enable all information on all issues and pull requests to be transferred across, although generally without hyperlinks other than those those linking within or between issues of the same repository.
All other hyperlinks, including any to GitHub users, or to other repositories, will be lost.
The transfer will be of information at the time the "New migration" on Codeberg or "New import" on GitLab is initiated.
From that time point on, any activity via issues or pull requests on any hosting platform will be specific to that platform only.[^2]

[^2]: There are tools for continuous mirroring such as [GitHubCodebergMirror](https://codeberg.org/wl/GithubCodebergMirror), but there is likely some fragility in these setups.

To transfer issues from GitHub to Codeberg, first click on the "GitHub" symbol in the "Migrate repository" options shown above, after which appears a dialog with options for what you would like migrated.
These options include "issues", "Pull requests", "Labels", "Milestones", and "Releases," also with the clear information that,

> Access token is required to migrate additional items

For that, you just need to paste a GitHub token in the Codeberg field, ensuring that the token has at least read access to all aspects you want transferred.
GitLab transfers issues, pull requests, tags, and releases by default, with even more possible through provision of a GitHub access token.
In both cases, transfer can take some time (10-20 minutes or more), following which all issues will appear exactly as on GitHub, but generally minus the hyperlinks described above.
Other code hosting platforms like [SourceHut](https://sr.ht/), or the distributed hosting system [tangled](https://tangled.org/) do not provide facilities for directly transferring or mirroring issues or pull requests (and in fact generally don't even have such things, as they really are specific to the GitHub platform; [SourceHut](https://sr.ht), for example, implements its own systems of "todos" and "patches".)
Comment on lines +99 to +119
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move some of this to the section on migration to Codeberg and GitLab (see those comments above) and to the section on Mirroring elsewhere (see the comments in that section).

Suggested change
## Transferring issues
Issues, pull requests, and other information on GitHub can be transferred both to Codeberg and GitLab, but only when a repository is first mirrored.
We are not currently aware of any platforms other these two which offer inbuilt ability to import additional information on issues and pull requests, although other people have implemented things such as [issue mirroring from GitHub to sourcehut](https://github.com/marketplace/actions/sourcehut-issue-maker).
Both Codeberg and GitLab enable all information on all issues and pull requests to be transferred across, although generally without hyperlinks other than those those linking within or between issues of the same repository.
All other hyperlinks, including any to GitHub users, or to other repositories, will be lost.
The transfer will be of information at the time the "New migration" on Codeberg or "New import" on GitLab is initiated.
From that time point on, any activity via issues or pull requests on any hosting platform will be specific to that platform only.[^2]
[^2]: There are tools for continuous mirroring such as [GitHubCodebergMirror](https://codeberg.org/wl/GithubCodebergMirror), but there is likely some fragility in these setups.
To transfer issues from GitHub to Codeberg, first click on the "GitHub" symbol in the "Migrate repository" options shown above, after which appears a dialog with options for what you would like migrated.
These options include "issues", "Pull requests", "Labels", "Milestones", and "Releases," also with the clear information that,
> Access token is required to migrate additional items
For that, you just need to paste a GitHub token in the Codeberg field, ensuring that the token has at least read access to all aspects you want transferred.
GitLab transfers issues, pull requests, tags, and releases by default, with even more possible through provision of a GitHub access token.
In both cases, transfer can take some time (10-20 minutes or more), following which all issues will appear exactly as on GitHub, but generally minus the hyperlinks described above.
Other code hosting platforms like [SourceHut](https://sr.ht/), or the distributed hosting system [tangled](https://tangled.org/) do not provide facilities for directly transferring or mirroring issues or pull requests (and in fact generally don't even have such things, as they really are specific to the GitHub platform; [SourceHut](https://sr.ht), for example, implements its own systems of "todos" and "patches".)
### A note on transferring issues
Issues, pull requests, and other information on GitHub can be transferred both to Codeberg and GitLab, but only when a repository is first migrated.
Both Codeberg and GitLab enable all information on all issues and pull requests to be transferred across, although generally without hyperlinks other than those those linking within or between issues of the same repository.
All other hyperlinks, including any to GitHub users, or to other repositories, will be lost.
The transfer will be of information at the time the "New migration" on Codeberg or "New import" on GitLab is initiated.
From that time point on, any activity via issues or pull requests on any hosting platform will be specific to that platform only.[^2]
[^2]: There are tools for continuous mirroring such as [GitHubCodebergMirror](https://codeberg.org/wl/GithubCodebergMirror), but there is likely some fragility in these setups.


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move here

Suggested change
### Migrating elsewhere
No other platforms currently offer the one-click migration functionality of Codeberg or GitLab.
To migrate in all other cases, you'll need to:
1. Create a new repository on the desired platform.
2. Set a `git remote` URL to the new destination.
3. `git push` to new remote.
The [git remote web page](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) provides more detail on working with remotes.
We are also not currently aware of any platforms other than Codeberg and GitLab which offer inbuilt ability to import additional information on issues and pull requests, although other people have implemented things such as [issue mirroring from GitHub to sourcehut](https://github.com/marketplace/actions/sourcehut-issue-maker).
Other code hosting platforms like [SourceHut](https://sr.ht/), or the distributed hosting system [tangled](https://tangled.org/) do not provide facilities for directly transferring or mirroring issues or pull requests (and in fact generally don't even have such things, as they really are specific to the GitHub platform; [SourceHut](https://sr.ht), for example, implements its own systems of "todos" and "patches").


## Managing one repository across multiple platforms
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Managing one repository across multiple platforms
## Mirroring: Managing one repository across multiple platforms


To be clear, this entire post is about moving away from having code hosted on a single platform, to distributing across multiple platforms through _mirroring_.
If, for example, you only want to migrate away from GitHub to some single, other platform, then both Codeberg and GitLab already offer the full solutions described above.
We nevertheless recommend mirroring across multiple platforms, to reduce risks associated with dependence on any single platform.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these risks?

Comment on lines +124 to +126
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To be clear, this entire post is about moving away from having code hosted on a single platform, to distributing across multiple platforms through _mirroring_.
If, for example, you only want to migrate away from GitHub to some single, other platform, then both Codeberg and GitLab already offer the full solutions described above.
We nevertheless recommend mirroring across multiple platforms, to reduce risks associated with dependence on any single platform.
The goal here is to move from having code hosted on a single platform to distributing code across multiple platforms through _mirroring_. This reduces the risks associated with dependence on any single platform, and also allows you to use an alternative platform to GitHub while still benefiting with GitHub operations used by other organizations (like rOpenSci!).
Therefore the next step is to setup mirroring which involves two parts,
adding remotes and then synchronizing those remotes.


As described above, the easiest way to manage one Git repository across multiple platforms is to use one primary source to which you `push`, and from where you may `pull`.
All other remote origins should be considered `push` mirrors only, and never `pull`.
In the rare case that conflicts from other sources arise, you may need to `git push --force` to _other_ remotes (or the [safer version of `git push --force-with-lease`](https://git-scm.com/docs/git-push#Documentation/git-push.txt---force-with-leaserefnameexpect)).
You should never `git push --force` to the main branch of your primary source.

### Adding remotes to your local Git information
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Adding remotes to your local Git information
### Adding multiple remotes


For each additional remote source, you'll need to add a remote URL with [`git remote add`](https://git-scm.com/docs/git-remote).
There are many ways to do this.
The pure Git way of managing multiple remote sources is to take advantage of `git remote set-url --add` to add additional URLs to a single remote identifier.
[This blog post](https://jeffkreeftmeijer.com/git-multiple-remotes/) details how to do that safely, to ensure only one primary remote is configured to `fetch`, while allowing `push` events to all others.
An alternative option would be to initially create an additional remote like `git remote add other https://codeberg.org/ropensci/my-package`.
You can then extend that with each additional remote URL with `set-url --add`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this line, how does this work?

Running `git push other <branch>` will then push that branch to all remote URLs specified in `other`.

Yet another approach is to define a [custom command](https://stackoverflow.com/questions/60060217/how-do-i-make-custom-git-commands) for `git push` to call a local script.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this paragraph really necessary? I find it complex and a bit confusing and possibly only useful to people trying to mass migrate & mirror a bunch of repositories. Could it be put in an appendix at the end perhaps?

This can be done by adding some "gitbin" directory to a default system `PATH` variable (in `.bashrc`, for example, as `export PATH="$PATH:$HOME/.gitbin"`).
Git will automatically recognize any scripts within `$PATH` named with the prefix "git-".
It is best to name locally-defined Git commands differently to standard Git commands.
For example, a file named `git-pushall` placed in that folder will be called by the `git pushall` command.
The file itself could contain any of the options described in [this StackOverflow answer](https://stackoverflow.com/a/18674313).
Even more arcane alternatives include my own [git push bash script](https://github.com/mpadge/dotfiles/blob/main/system/gitpush.bash) which recreates the now obsolete push-by-password functionality of GitHub, while also pushing to all other listed remote sources.

### Synchronizing multiple remotes

As with `git remote` setups described above, there are several ways to synchronize multiple remote instances of a single repository.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
As with `git remote` setups described above, there are several ways to synchronize multiple remote instances of a single repository.
As with the `git remote` setups described above, there are several ways to synchronize multiple remote instances of a single repository.

The pure Git way is to use local commands like those described and linked to above, to `git push` changes to all remote locations.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where? I would repeat it here

(This is the approach recommended by GitHub, but GitHub is an anomaly among code hosting platforms in offering no easy ability to interact with other platforms.)

Both Codeberg and GitLab offer mirroring services to enable these sites to be used as a primary site, and to mirror all code changes directly across to any alternative site such as GitHub.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Both Codeberg and GitLab offer mirroring services to enable these sites to be used as a primary site, and to mirror all code changes directly across to any alternative site such as GitHub.
However, both Codeberg and GitLab offer mirroring services to enable these sites to be used as a primary site, and to mirror all code changes directly across to alternative sites such as GitHub.

Codeberg has a "Mirror settings" option near the top of the general repository "_Settings_" panel, where you can easily specify an arbitrary number of mirror locations, and click "_Sync when commits are pushed_".
The GitLab settings are under "_Settings_" &rarr; "_Repository_", where you should see options for "_Mirroring repositories_".
Depending on how you configure your other repositories, you may need to add additional information such as public SSH keys to authenticate `git push` events.
Common options are described in [GitLab's documentation](https://docs.gitlab.com/user/project/repository/mirror/).

Finally, if you want to keep GitHub as your primary home while avoiding having to remember to use `git pushall` or whatever other local setup you may have or need, you can easily set up a GitHub action to automatically push your code across to any other locations.
While there are "marketplace" actions available to do this, we do not recommend those, as the procedure is very straightforward, and implementing your own is generally easier.
An example is [this workflow](https://github.com/ropensci/osmdata/blob/main/.github/workflows/push-to-elsewhere.yaml) which is run on every `push` event to the main branch and mirrors the [`github.com/ropensci/osmdata`](https://github.com/ropensci/osmdata/tree/main) repository across to both [`codeberg.org/ropensci/osmdata`](https://codeberg.org/ropensci/osmdata) and [`gitlab.com/ropensci/osmdata`](https://gitlab.com/ropensci/osmdata).


## Advertising your new code home
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Advertising your new code home
## Advertising your primary code home


Regardless of how your structure and disperse your code across multiple platforms, it's generally useful to maintain a single, primary "home".
(This is of course not at all necessary; if you enjoy dividing your attention across different platforms, please do so, and ignore this section.)
We recommend advertising your primary code location at the top of your README.md document, something along the lines of [this example](https://github.com/ropensci/osmdata#osmdata-), and clearly stating whether or not you will respond to "issues" (or whatever platform-specific interactions may be called) on any other platforms.

If your primary home is _not_ GitHub, then you can create an additional GitHub-specific `.github/README.md` file which will then be displayed on GitHub only, while all other platforms will display the root README contents.
An example is Doug Kelkhoff's [`github.com/dgkf/options` package](https://github.com/dgkf/options) which has a [`.github/README.md`](https://github.com/dgkf/options/tree/main/.github) explaining that GitHub hosts a read-only mirror of the repository, and directing people to the primary location at [`codeberg.org/dgkf/options`](https://codeberg.org/dgkf/options).
That primary location then displays the full contents of the root README file.
This trick only works for GitHub - all other platforms display the root README file at all times.

## Words of warning

Whatever approach you decide to explore, you're bound to realise that managing code distributed across multiple platforms is more difficult that on a single site.
Many features you might be used on GitHub, for example, may not be implemented on other platforms, or may have other names and inconsistent behaviours.
Comment on lines +181 to +182
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Whatever approach you decide to explore, you're bound to realise that managing code distributed across multiple platforms is more difficult that on a single site.
Many features you might be used on GitHub, for example, may not be implemented on other platforms, or may have other names and inconsistent behaviours.
Whatever approach you decide to explore, you're bound to realise that managing code distributed across multiple platforms is more difficult than on a single site.
Many features you might be used to on GitHub, for example, may not be implemented on other platforms, or may have other names and inconsistent behaviours.

One example is "Releases", which GitHub associates with Git tags, and then enables you to upload additional data to be associated with a release.
This whole procedure has little to do with Git, and a lot to do with design decisions by GitHub.
Other platforms offer similar functionality, but even then with caveats like:

- Codeberg can mirror all GitHub releases, but does not do so by default.
You need to:
- Go to repository "_Settings_" to enable releases
- Explicitly `git push --tags codeberg <branch-name>` to push all Git tags, as they are not by default included in Codeberg's mirroring process.

You should then see a mirror of all GitHub releases, including all ("LFS" = "Large File Storage") data.
From that point on, you will be able to create releases with additional data on Codeberg just like on GitHub.

- GitLab also does not mirror releases by default, and does not (currently) automatically track tags like Codeberg does.
To mirror releases on GitLab, you need to.
- `git push --tags gitlab <branch_name>`, just like on Codeberg, to explicitly push all Git tags.
- Manually go through each tag and issue a new release, for which you can retrospectively set the release data to be the same historical date as the original GitHub release date.

There are many other ways small and large by which different code-hosting platforms and systems differ from one another.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
There are many other ways small and large by which different code-hosting platforms and systems differ from one another.
There are many other ways, small and large, by which different code-hosting platforms and systems differ from one another.

Ongoing maintenance across different platforms will always present challenges, but we hope to have given you enough information here to get you started.


## rOpenSci repos on Codeberg, GitLab, or elsewhere

If you're an author of an rOpenSci package, you can follow the steps described above to mirror your code to any location on Codeberg, GitLab, or to any other platform.
Please let us know if you'd like any of these platforms other than GitHub to act as the primary home for your code, and we'll update our internal data accordingly.
We recommend moving repositories either to personal namespaces on these platforms, or to other organizational namespaces to which you have administrative access.

We also maintain the organizations [Codeberg/ropensci](https://codeberg.org/ropensci) or [GitLab/ropensci](https://gitlab.com/ropensci).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
We also maintain the organizations [Codeberg/ropensci](https://codeberg.org/ropensci) or [GitLab/ropensci](https://gitlab.com/ropensci).
We also maintain the organizations [Codeberg/ropensci](https://codeberg.org/ropensci) and [GitLab/ropensci](https://gitlab.com/ropensci).

Note, however, that mirroring to either of these locations must be initiated by rOpenSci staff, only after which can we grant you administrative access over your repositories.
To reduce the burden on rOpenSci staff, and to enable you to retain full control over your repositories, we therefore recommend that you mirror [GitHub/ropensci](https://github.com/ropensci) repositories to other locations (such as within your personal repositories) on these alternative platforms to which you have direct administrative access.
If you would nevertheless like your [GitHub/ropensci](https://github.com/ropensci) package mirrored to either [Codeberg/ropensci](https://codeberg.org/ropensci) or [GitLab/ropensci](https://gitlab.com/ropensci), the best way is to ping `@ropesnci/admin` from a GitHub issue in your repository, and we'll start the process.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.