This repository uses GitHub Actions to do mirroring of R source code from the SVN repository at https://svn.r-project.org/R/, to the git repository at https://github.com/wch/r-source.
It contains:
- A GitHub Actions workflow in
.github/workflows/
- git-svn metadata in
/svn/
- git-svn remote information in
refs/remotes/Rsvn
The process of mirroring the SVN repository involves two git repositories:
- r-source-git-svn (this one), which contains git-svn metadata
- r-source, which is a git repository which mirrors the SVN repository
A git repository which is set up to mirror a SVN repository using git-svn
(in this case the repository is r-source
) contains a directory /.git/svn
, which has metadata about the mappings between SVN and git commits.
The r-source/.git/svn
directory does not get pushed to remote git repositories. Normally that's not a problem because the repository persists on disk. However, with GitHub Actions, there is not persistent storage, so we need to save the r-source/.git/svn/
metadata some other way. We do it here by storing it in r-source-git-svn/svn/
, and then creating a symlink from r-source/.git/svn/
pointing to it, every time the workflow runs.
The strategy used by GitHub Actions workflow is:
- Clone this r-source-git-svn repository.
- Clone the r-source repository, into
r-source-git-svn/r-source/
. - Symlink
r-source-git-svn/r-source/.git/svn
to point tor-source-git-svn/svn/
. - Symlink the
r-source-git-svn/r-source/.git/refs/remotes/Rsvn
dir tor-source-git-svn/refs/remotes/Rsvn/
. - Do the
git svn
steps for mirroring SVN commits to the localr-source-git-svn/r-source/
repo. This will also update contents in the.git/svn/
directory. - Commit the changes to
r-source-git-svn/svn/
(the files here have changed becauser-source-git-svn/r-source/.git/svn/
is a symlink to it). - Push the changes to the r-source repository.
- Push the changes to the r-source-git-svn repository.
The same process can be done manually, with the commands below.
git clone https://github.com/wch/r-source-git-svn.git
cd r-source-git-svn
git clone https://github.com/wch/r-source.git
cd r-source/.git
ln -s ../../svn
cat <<EOF >> config
[svn-remote "svn"]
url = https://svn.r-project.org/R
fetch = trunk:refs/remotes/Rsvn/trunk
branches = branches/*:refs/remotes/Rsvn/*
tags = tags/*:refs/remotes/Rsvn/tags/*
EOF
cd refs/remotes
ln -s ../../../../refs/remotes/Rsvn
cd ../../..
git checkout trunk
git svn fetch
git svn rebase
# Push all branches from Rsvn to origin (r-source)
git push origin refs/remotes/Rsvn/*:refs/heads/*
# Commit changes to SVN metadata and push to r-source-git-svn
cd ..
git add svn refs
git commit -m"Update from SVN"
git push
The two repositories could get out of sync if a push to one of them succeeds, but a push to the other fails.
If the r-source repository gets ahead of the r-source-git-svn repository: that is not a problem (I think), because the next time git svn fetch
and git svn rebase
are run, they correctly match up the commits.
If the reverse happens, with r-source-git-svn getting ahead of r-source: this can be a problem, because the refs in refs/remotes/Rsvn
will point to git commits which do not exist. Here's a sample of the output you might see if that happens:
$ git svn fetch
error: refs/remotes/Rsvn/trunk does not point to a valid object!
$ git svn rebase
error: refs/remotes/Rsvn/trunk does not point to a valid object!
fatal: invalid upstream 'refs/remotes/Rsvn/trunk'
rebase refs/remotes/Rsvn/trunk: command returned error: 128
If this happens, the way to fix it is to go back in time, and check out commits in each repository at a point when they were in sync. Then you may need to do a git checkout -B trunk
(or whichever branch) to point it to the selected (old) commit. After doing that, the git svn fetch
and rebase
should work.
A git gc
in the r-source repo will remove the remote branches in .git/refs/remotes/Rsvn
. (This directory is a symlink to the r-source-git-svn/refs/remotes/Rsvn
.) The GitHub Actions workflow checks that these files are present; if not, it errors out before trying to commit and push changes.