Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to clone branches after cloning just trunk in git-svn?

Tags:

git

git-svn

Given a large Subversion repository with many branches, I want to start using git-svn by cloning trunk first and adding specific branches later. I saw at least three ways to do this, but are any of them "official" or is there a best way?

Assume the following layout:

https://svn-repo.com/svn/company
   +--core
   |  +--trunk
   |  +--branches
   |  |  +--fastboot
   |  |  +--playground
   |  +-tags
   +--mobile
      +--trunk
      +--branches
      +--tags

So, to clone only the trunk (no branches) revision 12345 of project core:

$ git svn clone --username=svnuser -r 12345 -Ttrunk https://svn-repo.com/svn/company/core

This will clone project core into a directory of the same name and running git svn rebase will pull in all the changes (after revision 12345). At this point .git/config should have something like this in it:

[svn-remote "svn"]
  url = https://svn-repo.com/svn/company
  fetch = core/trunk:refs/remotes/trunk

So far so good. Now, let's say I want to add the playground branch. This is where it gets a bit hazy.


Option 1: Update the existing remote in .git/config by adding the branch there:

[svn-remote "svn"]
  url = https://svn-repo.com/svn/company
  fetch = core/trunk:refs/remotes/trunk
  branches = core/branches/{playground}:refs/remotes/branches/*

At this point, I was able to do:

  1. Pull in revision 23456 of branch playground

    $ git svn fetch -r 23456

  2. Create a local branch and switch to it

    $ git checkout -b playground branches/playground

  3. Pull in the latest changes:

    $ git svn rebase


Option 2: Add a new remote in .git/config (in addition to the existing one):

[svn-remote "playground"]
  url = https://svn-repo.com/svn/company
  fetch = core/branches/playground:refs/remotes/playground

From here, the steps are similar to the ones from Option 1:

$ git svn fetch playground -r 23456
$ git checkout -b playground remotes/playground
$ git svn rebase

Option 3: I've also seen someone add a new fetch in the existing remote:

[svn-remote "svn"]
  url = https://svn-repo.com/svn/company
  fetch = core/trunk:refs/remotes/trunk
  fetch = core/branches/playground:refs/remotes/branches/playground

I'm not completely certain if that's correct or if it will even work. I can't find where I saw that.


Currently, I'm sticking with Option 1, but I would really like to know the most appropriate way to do this.

like image 458
Andrey Avatar asked Oct 04 '22 17:10

Andrey


1 Answers

All the options you note are valid, and there's no one "canonical" way to do this, partly because (from git svn's point of view) there's no one canonical way of laying out a Subversion repository.

Options 1 and 3 that you've picked out are essentially equivalent. Personally, I'd have gone with option 3, but the result will be identical to your option 1.

Option 2 would work, but it would prevent Git detecting commit history that crosses branches – Git will normally try to detect Subversion commits that merge or create branches, and record those as such in the Git commits, but it can't do that if it's treating the two branches as entirely separate repositories.

That said, by only adding the new branches at a later date, you're losing a lot of history already. Consider the following flow:

  • Your Git repository only contains git svn fetches of trunk.
  • Someone creates the playground branch from trunk, makes some commits in that branch, then merges playground to trunk.
  • You use git svn to fetch trunk; it sees the merge, but knowing nothing about the playground branch, adds it to the Git repository as a regular commit.

If you'd been picking up the playground branch all along, Git would have detected the branch and merge, and recorded them as such. Adding the playground branch afterwards won't help, unless you use git svn reset to re-fetch all the commits, because git svn won't rewrite the old commits to note the merge.

What I've done is to clone all the branches straight away, as Chronial suggested in the comments. It's a slow process (I've done this with a 100,000 commit Subversion repository with almost 300 branches and tags) that may take a few days to complete, but you can just leave it going in the background, and when it's done you'll have the complete Subversion history.

like image 145
me_and Avatar answered Oct 10 '22 06:10

me_and