Pushing an existing git repository to SVN

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 repo into git, but nothing about pushing a git repo to a fresh SVN repo. 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 repo when I choose, I wish to keep using Git and just have the SVN repo mirror what's in Git.

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

Any instructions on how to do this would be very much appreciated!


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 -> svn

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-repo, using dcommit . That's all.

Keeping repos in sync

You can now sync from svn -> git, using the following commands:

git svn fetch
git rebase trunk

And to sync from git -> svn, use:

git svn dcommit

Final note

You might want to try this out on a local copy, before applying to a live repo. You can make a copy of your git-repo to a temporary place, simply using cp -r , as all data is in the repo itself. You can then set up a file-based testing repo, 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.


Here's how we made it work :

Clone your git repo somwhere on your machine. Open .git/config and add the following(from http://www.kerrybuckley.org/2009/10/06/maintaining-a-read-only-svn-mirror-of-a-git-repository/):

[svn-remote "svn"]
    url = https://your.svn.repo
    fetch = :refs/remotes/git-svn

now, from a console window, type these :

git svn fetch svn
git checkout -b svn git-svn
git merge master

Now, if it breaks here for whatever reason, type these 3 lines :

git checkout --theirs .
git add .
git commit -m "some message"

and finally, you can commit to svn

git svn dcommit

note: I always scrap that folder afterwards.

cheers !


Using git rebase directly will lost the first commit. Git treats it different and cant rebase it.

There is a procedure that will preserve full history: http://kerneltrap.org/mailarchive/git/2008/10/26/3815034

I will transcribe the solution here, but credits are for Björn.

Initialize git-svn:

git svn init -s --prefix=svn/ https://svn/svn/SANDBOX/warren/test2

The --prefix gives you remote tracking branches like "svn/trunk" which is nice because you don't get ambiguous names if you call your local branch just "trunk" then. And -s is a shortcut for the standard trunk/tags/branches layout.

Fetch the initial stuff from svn:

git svn fetch

Now look up the hash of your root commit (should show a single commit):

git rev-list --parents master | grep '^.{40}$'

Then get the hash of the empty trunk commit:

git rev-parse svn/trunk

Create the graft:

echo <root-commit-hash> <svn-trunk-commit-hash> >> .git/info/grafts

Now, "gitk" should show svn/trunk as the first commit on which your master branch is based.

Make the graft permanent:

git filter-branch -- ^svn/trunk --all

Drop the graft:

rm .git/info/grafts

gitk should still show svn/trunk in the ancestry of master

Linearize your history on top of trunk:

git svn rebase

And now "git svn dcommit -n" should tell you that it is going to commit to trunk.

git svn dcommit
链接地址: http://www.djcxy.com/p/19452.html

上一篇: git:撤消所有工作目录更改,包括新文件

下一篇: 将现有的git存储库推送到SVN