Pushing an existing Git repository to SVN

2019-01-01 14:17发布

I've been doing all my work in Git and pushing to GitHub. I've been very happy with both the software and the site, and I have no wish to change my working practices at this point.

My PhD adviser is asking all students to keep their work in an SVN repository that's hosted at the university. I've found tons of documentation and tutorials about to pull down an existing SVN repository into Git, but nothing about pushing a Git repository to a fresh SVN repository. I expect there must be some way to do this with a combination of git-svn and a fresh branch and rebasing and all those wonderful terms, but I'm a Git newbie and don't feel confident with any of them.

I then want to just run a couple of commands to push commits to that SVN repository when I choose. I wish to keep using Git and just have the SVN repository mirror what's in Git.

I'll be the only person ever committing to SVN, if this makes any difference.

标签: svn git git-svn
16条回答
临风纵饮
2楼-- · 2019-01-01 14:17

In my case, I had to initiate a clean project from SVN

$ Project> git svn init protocol://path/to/repo -s
$ Project> git svn fetch

add all your project sources...

$ Project> git add .
$ Project> git commit -m "Importing project sources"
$ Project> git svn dcommit
查看更多
回忆,回不去的记忆
3楼-- · 2019-01-01 14:17

You can make a new SVN repository. Export your Git project (fleshing out the .git files). Add it to the SVN repository (initializing the repository with what you had so far in Git). Then use the instructions for importing SVN repositories in a fresh Git project.

But this will lose your previous Git history.

查看更多
美炸的是我
4楼-- · 2019-01-01 14:19

I needed this as well, and with the help of Bombe's answer + some fiddling around, I got it working. Here's the recipe:

Import Git -> Subversion

1. cd /path/to/git/localrepo
2. svn mkdir --parents protocol:///path/to/repo/PROJECT/trunk -m "Importing git repo"
3. git svn init protocol:///path/to/repo/PROJECT -s
4. git svn fetch
5. git rebase origin/trunk
5.1.  git status
5.2.  git add (conflicted-files)
5.3.  git rebase --continue
5.4.  (repeat 5.1.)
6. git svn dcommit

After #3 you'll get a cryptic message like this:

Using higher level of URL: protocol:///path/to/repo/PROJECT => protocol:///path/to/repo

Just ignore that.

When you run #5, you might get conflicts. Resolve these by adding files with state "unmerged" and resuming rebase. Eventually, you'll be done; then sync back to the SVN repository, using dcommit. That's all.

Keeping repositories in sync

You can now synchronise from SVN to Git, using the following commands:

git svn fetch
git rebase trunk

And to synchronise from Git to SVN, use:

git svn dcommit

Final note

You might want to try this out on a local copy, before applying to a live repository. You can make a copy of your Git repository to a temporary place; simply use cp -r, as all data is in the repository itself. You can then set up a file-based testing repository, using:

svnadmin create /home/name/tmp/test-repo

And check a working copy out, using:

svn co file:///home/name/tmp/test-repo svn-working-copy

That'll allow you to play around with things before making any lasting changes.

Addendum: If you mess up git svn init

If you accidentally run git svn init with the wrong URL, and you weren't smart enough to take a backup of your work (don't ask ...), you can't just run the same command again. You can however undo the changes by issuing:

rm -rf .git/svn
edit .git/config

And remove the section [svn-remote "svn"] section.

You can then run git svn init anew.

查看更多
泪湿衣
5楼-- · 2019-01-01 14:20

What if you don't want to commit every commit that you make in Git, to the SVN repository? What if you just want to selectively send commits up the pipe? Well, I have a better solution.

I keep one local Git repository where all I ever do is fetch and merge from SVN. That way I can make sure I'm including all the same changes as SVN, but I keep my commit history separate from the SVN entirely.

Then I keep a separate SVN local working copy that is in a separate folder. That's the one I make commits back to SVN from, and I simply use the SVN command line utility for that.

When I'm ready to commit my local Git repository's state to SVN, I simply copy the whole mess of files over into the local SVN working copy and commit it from there using SVN rather than Git.

This way I never have to do any rebasing, because rebasing is like freebasing.

查看更多
人间绝色
6楼-- · 2019-01-01 14:21

I just want to share some of my experience with the accepted answer. I did all steps and all was fine before I ran the last step:

git svn dcommit

$ git svn dcommit

Use of uninitialized value $u in substitution (s///) at /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm line 101.

Use of uninitialized value $u in concatenation (.) or string at /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm line 101. refs/remotes/origin/HEAD: 'https://192.168.2.101/svn/PROJECT_NAME' not found in ''

I found the thread https://github.com/nirvdrum/svn2git/issues/50 and finally the solution which I applied in the following file in line 101 /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm

I replaced

$u =~ s!^\Q$url\E(/|$)!! or die

with

if (!$u) {
    $u = $pathname;
} 
else {
       $u =~ s!^\Q$url\E(/|$)!! or die
      "$refname: '$url' not found in '$u'\n";
}

This fixed my issue.

查看更多
高级女魔头
7楼-- · 2019-01-01 14:22

Create a new directory in the Subversion repository for your project.

# svn mkdir --parents svn://ip/path/project/trunk

Change to your Git-managed project and initialize git-svn.

# git svn init svn://ip/path/project -s
# git svn fetch

This will create a single commit because your SVN project directory is still empty. Now rebase everything on that commit, git svn dcommit and you should be done. It will seriously mess up your commit dates, though.

查看更多
登录 后发表回答