April 23, 2019·4 min read·engineeringrubygitdevelopment

Ruby moves its canonical development repository to Git

Ruby adopts Git for its canonical development repository while retaining Subversion for existing stable branches. The migration changes source identity without adopting GitHub's merge workflow.

A repository can be visible on GitHub without GitHub being the place where a project accepts its canonical history. Ruby makes that distinction explicit in its April 23 migration announcement. The language's canonical development repository has moved from Subversion to Git, with a cgit web interface at git.ruby-lang.org. The GitHub repository remains a mirror under the announced policy.

The change allows Ruby to retain a contributor's commit hash directly in the project repository. That is a concrete improvement to source identity. It does not mean the project is adopting topic branches on its canonical server, merge commits, or GitHub's merge-pull-request button. The announcement explicitly excludes those workflows.

I appreciate the distinction because Ruby's readability has always mattered more to me than any particular hosting platform. A contribution process should make the change and its provenance understandable. Choosing Git supplies different tools for that process, while the project still has to define how maintainers use them.

Canonical history and public hosting are separate choices

A mirror gives readers another place to browse or obtain source. A canonical repository defines the history the project treats as authoritative. When both contain the same commits, the distinction can be easy to overlook. It becomes consequential when deciding where a maintainer should publish a change or which service controls acceptance.

Ruby's announcement keeps that authority at git.ruby-lang.org. The GitHub interface is therefore not sufficient documentation of the contribution workflow. A familiar button can exist on a hosting platform without being part of the project's approved process. Contributors need the policy that accompanies the repository, rather than assumptions imported from unrelated GitHub projects.

The no-merge-commit policy also expresses a separate decision. Git can represent branching and merging, but using Git does not require every supported history structure. A project can choose a linear accepted history while contributors prepare their work using local operations. The repository format and the accepted integration procedure answer different questions.

For readers investigating a defect, retained commit identity helps connect the contribution with the accepted change. When a contribution has to be represented through a different revision system, the reviewer and maintainer need a mapping between identities. Preserving the contribution's Git identity reduces that translation where the accepted workflow permits it.

Existing stable branches keep their existing workflow

The migration does not move every supported Ruby branch at once. The announcement says ruby_2_4, ruby_2_5, and ruby_2_6 continue to use Subversion. Maintainers must not push changes to their corresponding branches on the canonical Git server. Stable branches starting with ruby_2_7 will use the new Git arrangement.

That boundary is operationally important. The presence of a branch name in a Git view does not establish that the branch accepts writes there. A maintenance change needs to follow the workflow of its destination branch. Applying the development branch's new procedure indiscriminately would ignore the transition policy.

This is a reasonable form of staged migration. Existing release branches already have tooling and backport practices. Moving active development changes the path for new work while preserving the maintenance procedure for those established releases. The project accepts a period with two revision workflows in exchange for limiting the immediate change to stable-branch operations.

A backport also has a distinct purpose from the original development change. Its destination may have different surrounding code and a different release process. Even when the intended correction is the same, the maintenance revision needs an identity in its own workflow. The mixed Git and Subversion period makes that distinction visible.

I find that explicit branch boundary more useful than describing the migration as simply finished. A developer working on an older Ruby installation needs to know how its stable branch is maintained today. The development repository's new format does not erase the older branch's operating requirements.

Release tooling is part of a repository migration

The migration tracking issue began with an official Git repository that was still read-only. Its initial plan included moving snapshot tooling, improving access configuration, integrating repository references with Redmine, and eventually changing which server accepted writes. The canonical switch therefore followed preparatory work on the systems around the source tree.

The announcement credits k0kubun for release and backport tooling and Git hooks, and naruse for Ruby CI and Redmine changes. Those categories explain why the task is larger than copying files. A snapshot producer needs to obtain the intended revision. CI needs to test and identify it. An issue tracker needs to connect a reported correction with the relevant history.

A repository reference in a bug report is useful only when the surrounding system can resolve it. A release tool also needs to identify the source it is packaging. Changing the underlying history model without updating those consumers would leave correct source accompanied by misleading or broken metadata.

Hooks belong to the same operational contract. A repository can accept a push while notification or validation behavior differs from what maintainers expect. The migration therefore needs to preserve the intended process around an accepted change, not merely the ability to store the commit object.

An automation script that stores only a Subversion revision number also needs an explicit interpretation during the transition. A human may infer the intended branch from context, while an automated consumer needs a repository and revision format it can resolve. That requirement follows the history being referenced.

The initial issue also separates becoming writable from providing a browser. That is a useful way to reason about readiness. Public read access lets contributors inspect the new representation before the project changes where accepted changes arrive. It provides evidence about one capability without pretending to establish all the others.

Ruby's April announcement leaves further migration issues open for reporting through that tracker. The immediate policy is nevertheless specific enough to act on. Development history is canonical in Git, GitHub remains a mirror, and the existing 2.4 through 2.6 stable branches retain Subversion. A contributor choosing a workflow needs the destination branch and its current authority, as well as the source change itself.