Git clone from svn repo with no trunk directory and place files in root of git repo - git-svn

I'm importing code from a svn repository with a structure as follows:
Repo/
branches/
tags/
The repository doesn't have a trunk.
Code is kept in the subdirectory ProjectName, so when it's checked out I see
Repo/
ProjectName/
Files
When I execute:
git svn clone -t tags -b branches https://servername/svn/Repo GitRepo
I get a git repository at GitRepo and everything imports correctly, the problem is that whenever I check out files in git it checks them out into the ProjectName subdirectory like:
GitRepo/
ProjectName/
Files
My question is, is there any way way to tell git svn to clone the repo in such a way that I get:
GitRepo/
Files
So, what I'm asking is if I can tell git to use a folder that only appears when a branch is checked out as the root for the repository.

Yes you can do this, but you'll need to specify the trunk, branches and tag locations manually (as they're non standard in your case).
Create you're repo like so: git svn init https://servername/svn/Repo GitRepo
Then open up you .git/config file and the url, fetch, branches and tag lines so that it looks like the following:
[svn-remote "svn"]
url = https://servername/svn/Repo
fetch = ProjectName:refs/remotes/trunk
branches = branches/*:refs/remotes/branches/*
tags = tags/*:refs/remotes/tags/*
The important line here is fetch = ProjectName:refs/remotes/trunk which has created a link between ProjectName on the remote and trunk locally.

Turns out I needed:
[svn-remote "svn"]
url = https://servername/svn/Repo
branches = branches/*/*:refs/remotes/branches/*/*
tags = tags/*/*:refs/remotes/tags/*/*
in .git/config
The second /* in the branches and tags strings being the important part I was missing before.
Thanks to ChrisA for pointing me in the right direction.

Related

How do I migrate an SVN repository with custom structure to Git?

I have a multi-module legacy project in SVN, where individual modules were released and tagged separately, resulting in the following structure:
trunk/
project/
moduleX/
moduleY/
moduleZ/
tags/
moduleX-1.0/
moduleX-1.1/
moduleY-0.1/
moduleZ-2.0/
Looks like the tags were created with svn copy trunk/project/moduleX/ tags/moduleX-1.0/ etc, rather than svn copy trunk/project/ tags/moduleX-1.0
Is it possible to migrate such project to Git as a single repository, preserving history and creating appropriate tags?
You need to manually configure git-svn.
Create empty repositories: git init moduleX ; git init moduleY ; git init moduleZ
Edit each gitconfig and add a git-svn section like:
moduleX/.git/config:
[svn-remote "svn"]
url = svn://your-server/svn-repo
fetch = trunk/project/moduleX:refs/remotes/svn/trunk
tags = tags/moduleX-*:refs/remotes/svn/tags/*
moduleY/.git/config:
[svn-remote "svn"]
url = svn://your-server/svn-repo
fetch = trunk/project/moduleY:refs/remotes/svn/trunk
tags = tags/moduleY-*:refs/remotes/svn/tags/*
moduleZ/.git/config:
[svn-remote "svn"]
url = svn://your-server/svn-repo
fetch = trunk/project/moduleZ:refs/remotes/svn/trunk
tags = tags/moduleZ-*:refs/remotes/svn/tags/*
git svn fetch in each copy.

Accessing a mixed branches folder layout using git-svn

I am trying to use git svn to connect to our company repository. We have a slightly non-standard branches directory. How to access this using git svn has been discussed before, however, we seem to have a slight twist in our branch names that seems to keep me from getting them all.
Let's consider an example svn repo:
trunk/
tags/
branches/
rootbranch/
tku/subbranch
We have branches at the root level of the branches directory. But we have branches in nested folders, as well. The same goes for the tags dir, but I think that is just a second example of the same problem.
If I use git svn clone file:///tmp/gitsvn/svnrepo git-clone -s, I get only the root branches, as expected:
/tmp/gitsvn/git-clone$ git branch -r
rootbranch
tku
trunk
But if I clone using _git svn clone file:///tmp/gitsvn/svnrepo git-clone2 -b branches//_, I get only the sub-branches:
/tmp/gitsvn/git-clone2$ git branch -r
tku/subbranch
Is there a way to have both?
Additional branches can be accessed by adding multiple branches lines to the git-svn config.
In the .git/config file, there will be a section similar to the following:
[svn-remote "svn"]
url = http://server/svn
fetch = trunk:refs/remotes/trunk
branches = branches/*:refs/remotes/branches/*
tags = tags/*:refs/remotes/tags/*
Simply add another entry for the extra directory of branches. For example:
branches = branches/tku/*:refs/remotes/branches/tku/*
Then run git svn fetch to retrieve the branches from the svn repository.
I believe it's also possible to create this setup when constructing the git repository, using multiple -b options to the clone command.
git svn clone http://svn.foo.org/project -T trunk -b branches -b branches/tku -t tags
For anyone else who stumbles over this: it seems that having both is not possible. Subversion allows a mixed setup of branches, but it is discouraged, and so it seems okay that git does not support this. My solution was to bring all branches to the same level, then forget about the issue and move on. Having only one level of branches seems better anyway.

How can I change the Prefix Mapping in a Git-Svn Repository?

I've created a Git Clone of a SVN repository using git-svn. When doing this I specified the --prefix option to prefix my remote branches. I now want to get rid of this prefix.
Is there a way to update or remove the prefix without re-cloning the repository?
Essentially I did the initial clone using --prefix=Project so I ended up with Project/trunk and Project/feature-branch as my remote tracking branches. What I want is to have the trunk just be called trunk and the feature-branch be called svn/feature-branch.
I've done the following which appears to have worked.
In .git/config I updated the fetch, branches and tags settings to update the local refs. It was:
[svn-remote "svn"]
url = http://subversion/......
fetch = trunk:refs/remotes/Project/trunk
branches = branches/*:refs/remotes/Project/*
tags = tags/*:refs/remotes/Project/tags/*
Which I changed to
[svn-remote "svn"]
url = http://subversion/......
fetch = trunk:refs/remotes/trunk
branches = branches/*:refs/remotes/svn/*
tags = tags/*:refs/remotes/svn/tags/*
The within .git/refs/remotes I moved trunk out of the Project folder and the remaining refs within Project into a new folder called svn. The structure was:
remotes
Project
trunk
feature-branch
Which I changed to:
remotes
trunk
svn
feature-branch
I also performed the same restructuring of folders within .git/svn/refs/remotes/.
Finally I triggered a git svn fetch. I had to specify the -r argument to limit to the same start revision that I used for my initial clone, but it doesn't appear to have re-fetched the old revisions.
Note: the current solution might not work anymore with git 2.0+ (April 2014)
See commit fe191fc by Johan Herland (jherland), which highlight the fact you now are supposed to have a prefix (and not have a svn branch without prefix like 'trunk'):
Git 2.0: git svn: Set default --prefix='origin/' if --prefix is not given
Having no prefix by default was problematic:
git-svn by default puts its Subversion-tracking refs directly in refs/remotes/*.
This runs counter to Git's convention of using refs/remotes/$remote/* for storing remote-tracking branches.
Furthermore, combining git-svn with regular git remotes run the risk of clobbering refs under refs/remotes (e.g. if you have a git remote called "tags" with a "v1" branch, it will overlap with the git-svn's tracking branch for the "v1" tag from Subversion.

How can you use git-svn to clone parts of an SVN repo, but still get all the branches

Is there any way to use git-svn to clone only some folders of an SVN repo structure. I'm trying to clone a repo that has some crazy big binary files and a number of subfolders that are just plain useless. I've tried using the --ignore-paths option, but my clone seemed to just stall out doing nothing for an extremely long time. Have any of you managed to make --ignore-paths work? I can't find much on the webs where anyone else is running into this. Maybe I'm the only one.
We've used the "ignore-paths" feature to ignore certain directories in a svn repo:
[svn-remote "svn"]
ignore-paths = ^(((branches|tags)/[^/]+|trunk)|)(huge/|mobile/)
This config ignores the "huge" and "mobile" subdirs of the repository in trunk, all branches and all tags.
Perhaps you can illustrate the structure of your Subversion repository to make it easier for us to suggest some solutions.
Are you trying to git svn clone the entire repository from the root-url? Have you tried cloning smaller parts of the repo, and then perhaps grafting several clones together?
The most success I've had here is to manually create branches in git that mirror the SVN remote repository when necessary. The process has been the following:
Update .git/config file with:
[svn-remote "svn-branch-alias"]
url = http://svn/branches/crazybranchname/craziername/url/
fetch = :refs/remotes/git-branch-name
From the command line type: git svn fetch 'svn-branch-alias' to collect the SVN branch data into your local git repo.
Then type: git checkout 'git-branch-name' to go into a headless mode.
Finally type: git checkout 'my-local-git-branch-name' to create move head to the latest submission in that branch and create a local branch alias you can use.
You can now commit and dcommit as usual and still switch between various local git branches and your manually created SVN mirrors using the usual mechanisms.

How do I access svn branches using git-svn with a non-standard svn repo layout?

The standard repo layout in svn is as follows.
/trunk
/branches
featureX
featureY
/tags
1.0
2.0
The repository I'm working with is a much flatter structure.
trunk
featureX
featureY
Essentially, trunk is at the same level as the other branches. I can't use the -s or -b option with git svn init because of this.
How would I pull in trunk as the git branch master and pull in featureX as a git branch of the same name? I don't care about any other branches or tags.
I've seen similar questions and people have suggested restructuring the svn repository. This is off the table as far as this question is concerned.
I've figured out a way to pull in multiple branches from an arbitrary svn repository structure.
The -b option for git svn init will only work if all branches are grouped together within a subdirectory in the repository, such as in the standard layout. If all branches, including the trunk, are side by side in the same folder, this won't really work. You can pull in selected branches from the svn repository by essentially creating multiple "trunks" int your git repository.
Assume the flat structure from the question with the three branches trunk, featureX, and featureY.
Instantiate your git repository.
mkdir myproject
cd myproject
git svn init url:to/svn/repo -T trunk
This will create a git repository with svn metadata in the .git/config file.
Open the config file and examine the svn metadata
vim .git/config
Your config file will look something like this.
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
autocrlf = false
[svn-remote "svn"]
url = url:to/svn/repo
fetch = trunk:refs/remotes/trunk
The svn-remote header defines a reference called "svn" pointing to your svn repository. The fetch parameter tells git-svn where to pull new revisions from within the svn repository. Now we need to tell git-svn about the other branch we're interested in.
Duplicate the svn-remote section
Copy the entire svn-remote section of the config file and paste it below the existing config text.
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
autocrlf = false
[svn-remote "svn"]
url = url:to/svn/repo
fetch = trunk:refs/remotes/trunk
[svn-remote "svn"]
url = url:to/svn/repo
fetch = trunk:refs/remotes/trunk
Modify the new svn-remote section
Change the name of the svn-remote section header and the name of the branch that it points to.
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
autocrlf = false
[svn-remote "svn"]
url = url:to/svn/repo
fetch = trunk:refs/remotes/trunk
[svn-remote "svn-featureX"]
url = url:to/svn/repo
fetch = featureX:refs/remotes/featureX
Now git-svn will track both svn branches. You can use the names "svn" and "svn-featureX" with any git-svn command that takes an [svn-remote] parameter. You can use the names "trunk" and "featureX" with any git command that takes a remote branch name as a parameter.
This solution won't scale well, and is a bit of a hack to work with a malformed svn repository. So long as you only need to track a handful of svn branches, this will work just fine. If the number of svn branches you need to work with becomes too large, take a serious look at restructuring your svn repository to the standard layout.
As this article illustrates, you can write rules for running an importer tool like svn2git
(you have less complete version of svn2git here)
See those examples for rules that you could rewrite in order to match those flat SVN directories/branches and declare them as Git branches.