Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I keep SVN history in Git when trunk has moved?

Tags:

svn

git-svn

I am trying to use svn2git to migrate a SVN project to git. However I have problems preserving all the history. The reasons seems to be because the trunk was moved in the past. The command I am using is:

$ svn2git http://mysvnserver.com/myproject/iPhone/ --no-minimize-url --authors ../authors.txt

But this only gives me history going back to 2011. The project actually started in 2010. The projected started by looking like this:

myproject
   trunk
   branches
   tags

But in 2011 it was changed to this:

myproject
   iPhone
     trunk
     branches
     tags
   Android
      trunk
      branches
      tags

The old trunk and branches went under the iPhone directory. The history I get start from when this move was done. If I do svn log in the iPhone directory I get the shortened history. But if I cd trunk; svn log then I get the full history.

I have no idea of how to get this history out. My idea was to somehow create a git repository with only the history of the trunk going all the way back to 2010. Then I would later pull this in as a branch in my main repo, and do a rebase to get the history correct. But I have had no luck creating this repo for just the trunk. I have tried:

$ svn2git http://mysvnserver.com/myproject/ --rootistrunk --authors ../authors.txt

and

$ svn2git http://mysvnserver.com/myproject/ --rootistrunk -no-minimize-url --authors ../authors.txt

without any success.

like image 529
Erik Engheim Avatar asked Oct 17 '12 15:10

Erik Engheim


People also ask

Can I use Git and SVN at the same time?

No interaction between them. Just ignore the . git folder for SVN and the . svn folder for Git and you should be fine.

Which feature of Git makes attractive over SVN?

Git has the advantage that it's MUCH better suited if some developers are not always connected to the master repository. Also, it's much faster than SVN. And from what I hear, branching and merging support is a lot better (which is to be expected, as these are the core reasons it was written).


2 Answers

I just had the same problem myself. Here is how I solved it.

Clone both repos separately.

git svn clone -s [original-svn-location] [original-clone-directory]
git svn clone -s [new-svn-location] [new-clone-directory]

Add the old cloned data to the new repo.

cd [new-clone-directory]
git remote add oldstuff ../[original-clone-directory]
git fetch oldstuff

Now the tricky part... Do git log of master and of oldstuff/master (or maybe trunk and olstuff/trunk -- however you set it up) and write down the the first commit sha from the new clone and the last commit sha from the old clone (just before the move).

git replace [first-commit-sha-from-new-clone] [last-commit-sha-from-old-clone]

And to rewrite the SHA hashes so everything is kosher and you no longer need the replace ref...

git filter-branch

And now to clean up the no-longer-needed references.

git remote rm oldstuff
rm -rf .git/refs/replace

You will lose the first commit from your history, but since that should be the initial move (ie: no actual file contents have changed) it probably won't matter to you.

Now all history should still be maintained and git blame reports remember the repo's old history, giving you accurate information again.

You should be able to repeat this as often as needed (depending on how many times your project changed its root location and/or how many branches had commits on both sides of the move).

PS - This solution I adapted for my needs from one I found here (I couldn't get his graft approach to work for my repositories - but using replace seems to work beautifully).

like image 150
Shadow Man Avatar answered Oct 25 '22 01:10

Shadow Man


You can use SubGit to convert your SVN repository.

Unfortunately, version 1.0 does not support complex layout like that one you have. But there's 1.1 EAP version that handles it well. Both 1.0 and 1.1 versions work with local SVN repository, so you have to have administrative access to SVN repository.

Please do the following in order to convert SVN repository to Git:

  1. Generate initial configuration.

    $ subgit configure SVN_REPO
    
  2. Most probably, SubGit will detect two projects inside this repository. AFAIU, you need only one Git repository. So, you have to keep just one 'git' section in the config file. Specify all the branches you need to convert there.

    $ EDITOR SVN_REPO/conf/subgit.conf
    [core]
        ...
    [git "default"]
        repository = .git
        ...
        trunk = trunk:refs/heads/master
        branches = branches/*:refs/heads/*
        tags = tags/*:refs/tags/*
        shelves = shelves/*:refs/shelves/*
        branches = iPhone/trunk:refs/heads/iPhone/master
        branches = iPhone/branches/*:refs/heads/iPhone/*
        tags = iPhone/tags/*:refs/tags/iPhone/*
        branches = Android/trunk:refs/heads/Android/master
        branches = Android/branches/*:refs/heads/Android/*
        tags = Android/tags/*:refs/tags/Android/*
        ...
    [daemon]
        ...
    
  3. Convert SVN to Git.

    $ subgit install SVN_REPO
    
  4. At this moment SubGit converts all revisions from SVN to Git. You may find converted Git repository at SVN_REPO/.git. Additionally SubGit keeps SVN and Git repositories synchronized, it install special hooks to achieve that. If needed get rid of these hooks.

    $ subgit uninstall --purge SVN_REPO
    

That's all. Now you have converted Git repository with the whole history kept.

Note that SubGit is a commercial product, but this kind of one-time conversion is free. Hope, it works well for you.

like image 21
vadishev Avatar answered Oct 24 '22 23:10

vadishev