1

I'm trying to convert an SVN repository containing a Java EE application into a Git repository. The original repository contains a folder for each part of the Java EE project which has been maintained as separate projects history-wise. For two of the projects there's also a "production"-branch (again, two separate branches) and whenever a new revision goes into production trunk is merged up into production.

When I import this into one single git repository (as I understand would be best practice) everything in master is fine, but when I switch to a branch I only get the files of that branch and most of the other folders and files disappear.

Repository layout:

/
trunk/
   project1/
   project2/
   project3/
   project4/
branches/
   project3-production-branch/
   project4-production-branch/
tags/

I found a post by Eric Gwin about this issue, but I couldn't see there was any solutions to it. http://comments.gmane.org/gmane.comp.ide.eclipse.git/77

I might be overlooking something very elementary here, but I do fear that the only solution is to import the projects separetely? Any suggestions to how I can import the whole SVN-repo and get working branches in Git?

Darknight
  • 43
  • 6
  • How did you import it? Have you tried `git svn clone`'s `--stdlayout` switch? – mgarciaisaia Mar 18 '13 at 15:39
  • I suggest you rename the question to something more specific like "How to fix branches of partial directory structure in SVN to Git migration". – robinst Mar 18 '13 at 15:54
  • @desert69 I imported it using svn2git, but also tried using the method described at http://www.winklerweb.net/index.php/blog/4-eclipse/16-migrating-the-cdo-svn-repository-to-git with the same results. – Darknight Mar 18 '13 at 18:47

1 Answers1

1

Initial situation

After converting this to a single repository, the directory structure in master (or trunk) looks like this:

project1/
project2/
project3/
project4/

The structure after the first commit of the project3-production-branch looks either like this:

project3/

Or it contains the contents of project3 directly:

.project
src/
test/

This depends on where the branch was copied from in Subversion.

In the first case, the next step can be skipped.

In both cases, all other projects were removed on the branch (you should see that in the diff of the first commit) and need to be restored, see second step.

Step 1: Rewrite branch to move all contents into subdirectory (if needed)

See example "To move the whole tree into a subdirectory" in filter-branch and execute that only on the branch, like so:

git filter-branch --index-filter \
    'git ls-files -s | sed "s-\t\"*-&project3/-" |
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
            git update-index --index-info &&
     mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' \
     master..project3-production-branch

Step 2: Rewrite branch to restore other projects

In this step we want to undo the removal of the other projects in the first branch commit. This can be done using the following:

branch="project3-production-branch"
parent=`git merge-base $branch master` # or replace master with trunk if needed
paths="project1 project2 project4"
git filter-branch -f --index-filter \
"git reset -q $parent -- $paths" --tag-name-filter cat -- \
$parent..$branch

It resets the other paths to the state they were in when the branch was created, for all commits from the branch.

robinst
  • 30,027
  • 10
  • 102
  • 108
  • Haven't tried this out yet, but I fear that the assumptions are going to break. When I check out project3-production-branch in GIT the project3 folder disappears and all the files end up in the root of the repo. Technically, I can just move those around and commit the changes, but have to have the other files for the branch to make sense. Going to take a look at this now. – Darknight Mar 18 '13 at 18:50
  • Ok, this would have been helpful to have in the question. If you look at the history of the branch, does it start from the trunk (and does the start look reasonable) or is it entirely separate? And the first commit has lots of deletions and additions (possibly renames)? It's still possible to fix that, but it requires a separate pass of `filter-branch` first. Search for "To move the whole tree into a subdirectory" in [filter-branch](http://git-scm.com/docs/git-filter-branch). – robinst Mar 18 '13 at 22:41
  • After having tried out the solution outlined and been doing some testing, and diffing against svn and svn with branches it now seems that everything works and is the way it should be. The solution works as outlined, but I do get an error on "trunk" in parent (line 2) (think it said "no such object"). Nevertheless the rewrite worked OK (with the error message). Afterwards I moved the appropriate folders from the branches around with `git mv` so they ended up in the subfolders instead off in the root of the repo. Thanks :) – Darknight Mar 19 '13 at 02:18
  • Ok, then the branch is already called `master` (depends on how you did the migration from SVN). I updated my answer, if you redo it with the first step, even the older commits on the branch will be correct, as you don't have to do a `git mv` commit. – robinst Mar 19 '13 at 16:37