What is the Difference Between fetch and branch in the Git config file - git-svn

The config file of a Git repository has under [git-svn remotes] both fetch and branch paths. The config file can even have multiple fetch lines and multiple branch lines. What is the reason to have (and what is the difference between) both fetch and branch? When I do a git svn fetch --all, I get updates for the trunk in fetch and from all the other branch lines as well. So it seems there is no difference. Is there any drawback if I just list all my branches using multiple branch and not have any fetch line?
[svn-remote "messy-repo"]
url = http://server.org/svn
fetch = trunk/project-a:refs/remotes/project-a/trunk
fetch = branches/demos/june-project-a-demo:refs/remotes/project-a/demos/june-demo
branches = branches/server/*:refs/remotes/project-a/branches/*
branches = branches/demos/2011/*:refs/remotes/project-a/2011-demos/*

As illustrated here, the first git svn clone does generate a cnfig with fetch in it.
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.
From git svn clone
After a repository is cloned, the fetch command will be able to update revisions without affecting the working tree
The difference:
It is similar the core Git [remote] sections except fetch keys do not accept glob arguments; but they are instead handled by the branches and tags keys.

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.

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.

git svn as a crutch for svn merging woes

Consider an svn repository that has branches that are not necessarily located in the usual trunk/tags/branches layout. I want to persuade git-svn to take two of those branches on board, plus whatever else it needs, so that I can use git as a merge tool to avoid various levels of heck that have been plaguing us with svn merging. If the branches are all in one place, there's --branches, but is there a way if they are not?
Do your git svn init ROOT_URL, then go in and edit your .git/config to add additional fetchlines:
[svn-remote "svn"]
url = https://svn.mcs.anl.gov/repos/mpi
fetch = mpich2/trunk:refs/remotes/trunk
fetch = mpich2/branches/dev/threads:refs/remotes/threads
fetch = mpich2/branches/dev/knem:refs/remotes/knem
fetch = mpich2/branches/release/MPICH2_1_0_8:refs/remotes/mpich2-1.0.8
Then git fetch and you should get all of the branches explicitly listed in your config file.
Be aware, however, that you may not want to actually pursue merging externally via git-svn. Git won't maintain the svn:mergeinfo properties for you, which will make going back to a native SVN-based merge workflow nearly impossible. You might also confuse git-svn quite a bit by cherry-picking or merging code that has already been committed to the actual SVN repo, since it searches for git-svn-id: "breadcrumbs" in the commit messages in order to figure out which SVN path should be used for git svn dcommit. See the CAVEATS section of the git-svn man page for additional info about this.
FWIW, I've also posted about this in longer form on my own site.

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 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.