gitsvnsvn-externalsgit-tag

How to convert svn:externals to git tags


I'm working on converting a pretty decently sized SVN repo. It is ~50 projects which comprise ~5 different deliverable products (some projects are shared amongst all products, others projects are shared with only a couple products, and many projects that are unique to a specific product). There is about 15years of code history here (~16K svn revisions).

Early on after converting to SVN, we used SVN:externals to tag some of our releases. Our code structure (on disk after checkout) is as follows:

product1_root
  -> shared_project
  -> project_1
  -> project_2
  -> project_3
product2_root
  -> shared_project
  -> project_4
  -> project_5

The structure in SVN is as follows (b/t/tr) = standard branches/tags/trunk subdirs:

product1_root (b/t/tr)
shared_project (b/t/tr)
project_1 (b/t/tr)
project_2 (b/t/tr)
project_3 (b/t/tr)
product2_root (b/t/tr)
project_4 (b/t/tr)
project_5 (b/t/tr)

When using externals, externals were setup on the product1_root and product2_root projects to link in shared/project2/3 and shared/project4/5 respectively so that they create the above structure on disk. As a result, when doing releases, only the product1/2_root projects received tags (the SVN externals would pull the appropriate versions of subprojects automatically).

we later got rid of the externals in favor of explicitly tagging all the projects and using scripts to pull them all for builds.

Is there a way to propogate the tags from product1_root into project_1, project_2, project_3, and shared_project during the migration so that they match the rest of the history in the new git repo.

Or should I be looking into trying to tackle this as either a pre or post migration task?

I've looked at a lot of different tools and they all seem to either ignore the svn:externals entirely, or try to convert them to submodules.


Solution

  • I finally figured this out. Keep in mind that my svn:externals are setup to point to a specific peg in the repo (not head) so this may not work if you aren't in the same boat.

    Also, your migration from SVN to git must be done chronological in terms of the revision history in SVN has to be processed in order. The following two commands will do this (source):

    git svn init [SVN repo url] --stdlayout --prefix=svn/
    git svn fetch
    

    This assumes you have a standard SVN repo layout (branches/tags/trunk). If yours differs, you will need to modify the above command. The above command also prefixes everything with svn/ just to indicate that these were imported from svn instead of native git created content (for future reference in case you need it).

    Once that finishes (it takes about 90mins to pull a single project out of my 16K revision SVN repo). You can then lookup the date that your svn:externals tag was created in the SVN repo and find out the appropriate git commit that correlates for your project using the following command:

    git log --before='CCYY-MM-DD' -1
    

    The output will be in the following format:

    commit a22182ca563928b4de2143ff98dd0362f9eca36d
    Author: <author>
    Date:   Wed Oct 31 21:58:01 2012 +0000
    
    <Commit comment>
    

    Lastly, take the first several characters of the commit hash and create your tag in git:

    git tag -a v6.1.1.3 a22182 -m "manually creating git tag for svn:externals based tag"
    

    Verify the tag is the same in your git repo and your SVN repo and then continue on with the rest of your conversion.