Accessing a mixed branches folder layout using git-svn - 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.

Related

I'd like to move over a branch from an svn location and use it as the master in the github location

I'd like to move over a branch from an svn location and use it as the master in the github location. Can anyone tell how to do this?
You can follow this process by Tiago Rodrigues (trodrigues)
If you want to clone an svn repository with git-svn but don't want it to push all the existing branches, here's what you should do.
Clone with git-svn using the -T parameter to define your trunk path inside the svnrepo, at the same time instructing it to clone only the trunk:
git svn clone -T trunk http://example.com/PROJECT
If instead of cloning trunk you just want to clone a certain branch, do the same thing but change the path given to -T:
git svn clone -T branches/somefeature http://example.com/PROJECT
This way, git svn will think that branch is the trunk and generate the following config on your .git/config file:
[svn-remote "svn"]
url = https://example.com/
fetch = PROJECT/branches/somefeature:refs/remotes/trunk
If at any point after this you want to checkout additional branches, you first need to add it on your configuration file:
[svn-remote "svn"]
url = https://example.com/
fetch = PROJECT/branches/somefeature:refs/remotes/trunk
branches = PROJECT/branches/{anotherfeature}:refs/remotes/*
The branches config always needs a glob. In this case, we're just specifying just one branch but we could specify more, comma separating them, or all with a *.
After this, issue the following command:
git svn fetch
Sit back. It's gonna take a while, and on large repos it might even fail. Sometimes just hitting CTRL+C and starting over solves it. Some dark magic here.
After this, if you issue a git branch -r you can see your remote branch definitions:
git branch -r
anotherfeature
From there you can define a master branch, and push it to a GitHub repo:
git checkout -b master anotherfeature
git remote add origin https://github.com/user/arepo.git
git push -u origin master
If you insist on using git-svn, VonC already provided a good answer.
But for a one-time migration git-svn is not the right tool for conversions of repositories or parts of repositories. It is a great tool if you want to use Git as frontend for an existing SVN server, but for one-time conversions you should not use git-svn, but svn2git which is much more suited for this use-case.
There are plenty tools called svn2git, the probably best one is the KDE one from https://github.com/svn-all-fast-export/svn2git. I strongly recommend using that svn2git tool. It is the best I know available out there and it is very flexible in what you can do with its rules files.
You will be easily able to configure svn2gits rule file to produce the result you want from your current SVN layout, including any complex histories like yours that might exist and including producing several Git repos out of one SVN repo or combining different SVN repos into one Git repo cleanly in one run if you like.
If you are not 100% about the history of your repository, svneverever from http://blog.hartwork.org/?p=763 is a great tool to investigate the history of an SVN repository when migrating it to Git.
Even though git-svn or the nirvdrum svn2git is easier to start with, here are some further reasons why using the KDE svn2git instead of git-svn is superior, besides its flexibility:
the history is rebuilt much better and cleaner by svn2git (if the correct one is used), this is especially the case for more complex histories with branches and merges and so on
the tags are real tags and not branches in Git
with git-svn the tags contain an extra empty commit which also makes them not part of the branches, so a normal fetch will not get them until you give --tags to the command as by default only tags pointing to fetched branches are fetched also. With the proper svn2git tags are where they belong
if you changed layout in SVN you can easily configure this with svn2git, with git-svn you will loose history eventually
with svn2git you can also split one SVN repository into multiple Git repositories easily
or combine multiple SVN repositories in the same SVN root into one Git repository easily
the conversion is a gazillion times faster with the correct svn2git than with git-svn
You see, there are many reasons why git-svn is worse and the KDE svn2git is superior. :-)

git-svn branching when all submodules on same level

My project uses svn and I went git along time ago. I've been using git-svn for quite a while with a lot of success. But now at a new employeer, I'm having some problems.
The layout in SVN is:
http://path/to
/trunk/
submodule1
submodule2
/branches/
branch1
submodule1
branch2
submodule1
submodule2
I checked-out my git-svn to track each submodule (which I think is the right way to go).
git svn clone http://path/to/trunk/submodule1
git svn clone http://path/to/trunk/submodule2
Which gives me trunk, but I can't figure out how to track each branch. I want to think that --prefix would help me, I don't think that it will.
Anyone have ideas?
You should be able to achieve this using wildcards in your layout specification. I.e. for submodule1 you would do
git svn clone --trunk=trunk/submodule1
--branches=branches/*/submodule1 \
--tags=tags/*/submodule1 \
http://path/to
(assuming you also had tags following the same pattern). Repeat the same for the other submodules.
The --prefix option has nothing to do with this. It just controls how the branches will be named in the resultin git repository. Without the option, all branches will go straight under refs/remotes/. If you'd like something more like the usual remote branch layout, you can use e.g.
git svn clone --prefix=svn/ ...
to get refs/remotes/svn/trunk, refs/remotes/svn/branch1 etc. The value is prepended verbatim to the resulting branch names, so you need the trailing / or you'll end up with something like refs/remotes/svntrunk

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

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.

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.