52

Treating my repository as a SVN repo, I get:

svn co http://myrepo/foo/trunk foo
...
foo/
  bar/
  baz/ -> http://myrepo/baz/trunk

Treating it as a Git repo, I get:

git svn clone http://myrepo/foo --trunk=trunk --branches=branches --tags=tags
...
foo/
  bar/

I can clone baz to my local machine elsewhere and add a symlink, but that's just a hack. Is there a way to have git svn rebase automatically pull in those changes when it updates everything else, just like svn up does?

Jonas
  • 121,568
  • 97
  • 310
  • 388
James A. Rosen
  • 64,193
  • 61
  • 179
  • 261
  • I know I've read somewhere about how to set this up with git submodules, but I can't find the link. – JesperE Jan 23 '09 at 18:56

8 Answers8

26

The best means of integrating svn externals with git-svn that I've seen is this script, which clones your externals into a .git_externals/ directory and creates the symlinks and exclude files you need. I find this a simple and direct solution. YMMV.

Here is an older overview of other options for dealing with svn externals with git-svn. To me they look a little over-complicated and liable to break under subsequent Git use.

Paul
  • 16,255
  • 3
  • 33
  • 25
25

The solution I ended up using was just to symlink to other git-svn clones on my local box. This worked pretty well: it allows me to commit changes back, and it allows me to make local changes on project A just to get them into project B.

James A. Rosen
  • 64,193
  • 61
  • 179
  • 261
6

I just wrote a short script which checkouts all svn:externals of the current HEAD to the root directory and excludes them from the git repository.

Place it to .git/hooks/post-checkout and it will keep those external checkouts up to date whenever the working tree changes, for example due to git svn rebase or git-checkout.

#!/bin/bash
set -eu

revision=$(git svn info | sed -n 's/^Revision: \([1-9][0-9]*\)$/\1/p')
git svn -r${revision} propget svn:externals | head -n-1 | {
    while read checkout_args
    do
        checkout_dirname=$(echo ${checkout_args} | cut -d' ' -f3)
        svn checkout ${checkout_args}
        if [ -z $(grep ${checkout_dirname} .git/info/exclude) ]
        then
            echo ${checkout_dirname} >> .git/info/exclude
        fi
    done
}
tuomasjjrasanen
  • 435
  • 3
  • 6
4

I also made a script (both Perl and Ruby variants available) that does this for me, it's at http://github.com/liyanage/git-tools/.

  • Recursively checks out all svn:externals
  • Can be run repeatedly in case the clone of a large repository aborts halfway through. Happened to me a lot. It picks up where it left off.
  • Adds all svn:externals entries it finds and processes to .git/info/exclude
  • Adds all svn:ignore entries it encounters to .git/info/exclude
  • Can be run regularly after the first run to do the svn:rebase in all cloned sub-sandboxes, discover new externals and new svn:ignores

Update: I am no longer maintaining this script. Its functionality for recursively cloning and updating an SVN repository, as well as other git-related features, is available in this newer project that I am actively maintaining: http://liyanage.github.com/git-tools/

Marc Liyanage
  • 4,601
  • 2
  • 28
  • 28
  • 1
    I'd like to learn what didn't work for you so I can improve the script. Can you contact me? – Marc Liyanage Aug 16 '10 at 16:19
  • There's a lot of forks. Does anyone know which one of them works on windows with msysgit? The linked version just hangs. – axk Mar 02 '12 at 14:33
  • Couldn't make it work either. The documentation seems out of sync. `gh clone-externals` is not recognized as a valid subcommand. – Plouff Jun 30 '16 at 11:19
2

Just for the record: I followed this suggestion and tried using SmartGit for dealing with svn:externals.

SmartGit is by far the best GUI client I've ever seen for Git. Regarding svn:externals, it not only correctly fetches them, but also presents the option of doing a "fast snapshot" (read-only, HEAD-only clone) of external repositories.

Unfortunately it is not free for commercial use (and I found the license price a little bit too high - yes I'm a cheapskate). It may be used for free for non-commercial purposes though.

Community
  • 1
  • 1
rsenna
  • 11,775
  • 1
  • 54
  • 60
1

I decided to write a "simple" perl script to handle all this stuff for me. I've put it recently to github, try it out, maybe it would help: http://github.com/sushdm/git_svn_externals/.

It essentially does git-svn clone for all externals found, and it looks for them recursively, clones, symlinks them in proper places and excludes all .git_externals dirs and symlinks so that you can still use 'git svn dcommit'.

Good luck.

Dmitry
  • 6,590
  • 2
  • 26
  • 19
1

Here's what I've done.

First I created an empty SVN repo (for the same root as the git):

svn checkout --depth empty http://path/to/repo .

This created empty svn repo in the git root. The point is that is contains the SVN externals properties.

Next I simply check only the externals (I placed in PATH cygwin tools):

svn propget svn:externals | sed -e 's/ / .\//' | sed -e 's/\'//g' | xargs -L1 svn co
TCS
  • 5,790
  • 5
  • 54
  • 86
1

try this python script https://bitbucket.org/nytmyn/gitsvnext/overview

to checkout svn externals run following in your git repository

python /../gitsvnext/run update

run this to know what to put to .git/info/exclude

python /../gitsvnext/run list
opekar
  • 11
  • 1
  • Which folder would you run this against? If my main svn repository is /path/to/repo and the externals are defined inside /path/to/repo/myexternals/folder/ then should I run the script inside /path/to/repo or myexternals/folder? – Bibek Shrestha Jan 04 '13 at 14:24