One push, three platforms
Keeping a repository on more than one platform is normally a chore made of shell aliases: a remote per host, a loop that pushes to each, and a mental note…
Keeping a repository on more than one platform is normally a chore made of shell aliases: a remote per host, a loop that pushes to each, and a mental note about which one CI actually watches. torii models it instead.
Primary and replicas
torii mirror add gitlab user paskidev gitorii --primary
torii mirror add github user paskidev gitorii
torii mirror add codeberg user paskidev gitorii
torii mirror syncOne of them is the primary. That is not a label — it decides which platform torii pipeline, torii issue and torii release talk to when you do not say. The replicas are copies of the history and nothing else. torii mirror promote github user swaps which is which, for the day the primary is down or you move house.
Each remote keeps its own credentials
A mirror is not a mirror of your tokens. Each host has its own entry in auth.toml, its own scopes, its own expiry. This matters more than it sounds: a token that can push to your replica cannot necessarily open a pull request on your primary, and torii will tell you which one is missing rather than failing with a 403 and no context.
What happens when one rejects
mirror sync pushes to each remote in turn. A replica that rejects — a protected branch, a stale token, a host that is down — does not roll back the pushes that already succeeded. There is no distributed transaction here and pretending otherwise would be worse: you would get a "failed" that hides the fact that two of your three remotes are now ahead.
The output names each remote and what happened to it. Fix the one that failed and run it again; the ones that succeeded are no-ops the second time.
Autofetch
torii mirror autofetch --enable --interval 30m
torii mirror autofetch --statusFetches from the primary in the background so torii status tells you the truth about how far behind you are without a round trip first.
When to use this and when not to
Mirrors are for the same repository living in several places: an open-source project that wants a Codeberg presence, a company moving off one platform onto another over six months, a project that wants a copy outside a jurisdiction. They are not a substitute for a backup — three copies of a force-push are three broken histories — and they are not a way to split work across platforms, because there is exactly one history and every remote gets all of it.