My SVN structure is like this:
/
|-- Branch1
|-- Branch2
|-- Branch3
...
How can I clone this into a git repository preserving the branches (i.e. not flat history)?
Bonus question: How to clone only a subset of the SVN branches into a new git repository?
I believe that in SVN branches are just folders, its just a convention. Git actually works with branches. With this the approach becomes easier.
As you need to fetch the data from SVN repository you will need to create remote for it. From the structure I see that you need to create Branch 1 to 3 in your git repository.
Create Git repository.
git init
git config --local --add user.name <Username>
git config --local --add user.email <email>
echo "MASTER" > master
git add master
git commit -m "Dummy commit"
Create Remote of your SVN branch.
git config --add svn-remote.<BranchName>.url <SVN URL>
git config --add svn-remote.<BranchName>.fetch :refs/remotes/<RemoteName>
for Branch1:
git config --add svn-remote.branch1.url https://svnhost/svn/MyRepo/Branch1
git config --add svn-remote.branch1.fetch :refs/remotes/branch1_remote
Fetch SVN data of branch1:
git svn fetch branch1
Repeat this for other two branches Branch2 and Branch3.
You can stop right here if you are only trying to clone You need not proceed further unless you want to work with Git repository. Google on git subtree to know why this could be correct solution in your case.
To Create Subtree:
Find last commit id:
git checkout remotes/branch1_remote
git svn log -n 1 --show-commit --oneline
Output: 734713bc047d87bf7eac9674765ae793478c50d3 (This is yout LastCommitId value)
Create subtree in mainline master branch:
git checkout master
git subtree add --prefix=Branch1 <LastCommitId>
For you bonus question: Try this
git svn clone https://svnhost/svn/MyRepo/Branch2
This one is simple, the other way is to follow the above steps and instead of creating three remotes in same repository create new repository everytime and then add your branch's remote. Based on your requirement you could google out different ways.
Clone just the first few revisions of only trunk before any branches were created. I'm assuming that your branches were not created before revision 5. I'm also assuming that your trunk folder is named trunk
. Adjust accordingly. Hopefully you have already created an authors file as well. This will set up the local repository.
$ git svn clone https://svn.example.com/myrepo --authors-file=authors.txt -T trunk -r 1:5 myrepo
Next, add branches
lines in myrepo/.git/config
similar to this:
[svn-remote "svn"]
url = https://svn.example.com/myrepo
fetch = trunk:refs/remotes/origin/trunk
branches = branches/Branch1:refs/remotes/origin/*
branches = branches/Branch2:refs/remotes/origin/*
branches = branches/Branch3:refs/remotes/origin/*
If your branches follow a naming convention that can be matched with a pattern like in your example, you could do this:
[svn-remote "svn"]
url = https://svn.example.com/myrepo
fetch = trunk:refs/remotes/origin/trunk
branches = branches/Branch*:refs/remotes/origin/*
Some people recommend deleting myrepo/.git/svn/.metadata
after making these edits. I don't know if that is necessary or not.
Now you just fetch the remaining revisions. Git svn will work out the branch structure and do the right thing. Any branches that don't match one of the branches
lines will be ignored.
$ cd myrepo
$ git svn fetch
Once it is complete, you can check that the branches were created with this command.
$ git branch -r
origin/Branch1
origin/Branch2
origin/Branch3
origin/trunk