tags:

views:

520

answers:

3

So I've converted an SVN repository to a git repository using svn2git, because I assumed there wouldn't be any more work on the svn repository. However, someone else didn't know that we were switching to git (it's a bit complicated, but he was basically just working on one specific file) so he made some commits to SVN. Now I want to get these commits into git. Can I still do this, or is svn2git completely one-way?

If not, is there a way to generate patches from SVN commits, sort of an analog to git format-patch? I can't seem to find one from a cursory search; it seems like the SVN developers never thought you would want to convert commits into patches.

+3  A: 

You might take a look at git-svn.

Manual patches in Subversion are done via diff.

Amber
@Dav: good comment (I have deleted my answer). +1 for your post
VonC
Well right, I know about git svn, but I didn't use it partly because I wanted to forget that svn ever existed ;). Obviously svn2git is sort of just a wrapper around git svn clone which does some cleanup work. At this point there are a bunch of things that I've committed to git via patches and I don't want to use git svn and reapply all my patches again, since we're moving off of svn anyway.But I think the manual patches approach should work for me, and then I can commit them with the proper author or let him commit them himself once he gives me an ssh key for gitosis.
Ibrahim
Wait a minute, that manual diff approach isn't what I wanted. It doesn't work for things that are already committed into SVN, just things that are different between the SVN head and the working copy.
Ibrahim
You can take diffs between two revisions in an svn history instead of 1 revision + working copy. Just specify both revisions you want to diff: `svn diff -r rev1:rev2`
Amber
svn2git is, indeed, just a wrapper around git-svn and the original repository that it creates can pull more changes from svn by using git svn commands. I had to do this myself recently.I hacked together a modified ruby script that does only the followup steps (which mostly involve converting svn tags to git tags) so that I could do a git svn fetch in the repo and then do the rest of svn2git's processing on the newly pulled stuff.
ebneter
+1  A: 

From your description it sounds like there were only a few commits in Subversion that you want to pick up. The most direct method is to extract and apply each patch manually, which I'll outline here. First, you can use the svn diff command to extract the diffs (a "diff" is functionally equivalent to a "patch").

svn diff -r 101:102

This will show the diff between revision 101 and 102. You can redirect this output into a file for use in the next step:

svn diff -r 101:102 >r102.patch

In the Git repository, take the diff from the previous step and apply it using the patch program:

patch -p0 <r102.patch

The -p0 tells the patch program how to look for the file(s) named in the patch. Finally, commit the changes to Git:

git add -u
env GIT_AUTHOR_NAME="new name" GIT_AUTHOR_EMAIL="new email" git commit

The GIT_AUTHOR_* environment variables allow you to preserve the original author information, which may be useful for history maintenance.

The above should work easily enough for text files, but if any changed files in Subversion happen to be binary files, you'll have to use a slightly different technique (Subversion will refuse to produce a useful diff in this case). Instead of extracting patches and applying, just copy the file(s) from each Subversion revision to the Git repository before committing. This would actually work just fine for text files too, if you prefer.

Greg Hewgill
Cool, I wasn't sure how to use svn diff on revisions, probably should have just RTFM. I was being lazy and just using TortoiseSVN. This is exactly what I wanted, although I might just redo the svn2git script and then add my patches on top again.
Ibrahim
A: 

I actually found another way of doing this. I ran svn2git again, got a more updated git clone of the svn repository. Then in my old git repository, I added the newer clone as a remote, fetched it, and then used git rebase svnclone2/master to rebase my branch onto the newly updated svn2git branch.

Of course, this means that my commits that were rebased have the same commit time, but this is not too bad. It's less work than manually doing patches, and since this git repository is still not being used by anyone other than me yet, I could rewrite history without worrying about the consequences. But this is probably not a good solution in general; the best thing would be to get the original committer to get git access (he is a mercurial fan heh) and have him commit the patches himself.

Ibrahim