Git подмодуль svn внешний

Скажем, у меня есть 3 git репозитории, каждая с папкой lib и tests в корне. Все 3 хранилища являются частью того, что я хочу быть единственным пакетом, однако для меня важно сохранить отдельные репозитории.

Я новичок в git, исходящий из svn, поэтому я читал на submodules и как они отличаются от svn:externals. В SVN у меня может быть один

lib/vendor/package

а внутри package я мог бы настроить 3 внешних элемента, указывающих на каждый из моих 3-х репозиториев lib, переименовывая его соответствующим образом, как

lib/vendor/package/a  -> repo1/lib
lib/vendor/package/b  -> repo2/lib
lib/vendor/package/c  -> repo3/lib

но из моего понимания это невозможно с помощью git. Я что-то пропустил?

На самом деле я надеюсь, что это можно решить одним из двух способов.

  • Кто-то укажет, как создать 4-й репозиторий git, который имеет другие 3 в качестве подмодулей, организованных, как я уже упоминал выше (где я могу иметь папку a, b и c внутри корень)
  • Кто-то укажет, как установить это с помощью svn:externals в сочетании с поддержкой githubs svn, ссылаясь на каталог lib в каждом хранилище git (из моего понимания это невозможно).

Обновление:

Я действительно пытался следить за учебником подмодулей, с которым вы связались, но я столкнулся с следующей проблемой.

Выполнение действий, как показано выше, вместо отображения типа

lib/vendor/package/a  -> repo1/lib
lib/vendor/package/b  -> repo2/lib
lib/vendor/package/c  -> repo3/lib

Я остался с

lib/vendor/package/a  -> repo1
lib/vendor/package/b  -> repo2
lib/vendor/package/c  -> repo3

это не идеально, поскольку теперь для доступа к ClassA внутри папки repo1 lib путь

lib/vendor/package/a/lib/ClassA

когда я действительно пытаюсь получить (и это возможно с помощью svn: externals)

lib/vendor/package/a/ClassA

поскольку a выше на самом деле repo1/lib, а не корневой каталог repo1.

Что-то вроде этого важно, поскольку, например, PHP5.3, используя SplClassLoader (http://gist.github.com/221634), это требует отображение пространства имен в каталог, например

\Package\a\ClassA  -> lib/vendor/package/a/ClassA

Вот где мое концептуальное недоразумение заключается в том, как настроить этот 4-й репозиторий git, чтобы разрешить мои сопоставления каталогов, как указано выше.

Ответ 1

Вы правы, Git подмодули не могут напрямую делать именно то, что вы хотите. Он работает в SVN, потому что корень репозитория, ветки и любой его подкаталог - это один и тот же объект. В Git репозиторий, ветвь и каталог представляют собой различные виды объектов (вы не можете использовать каталог как полный репозиторий или как ветвь).

Есть несколько косвенных способов выполнить то, что вы хотите.

Использование субмодулей и символических ссылок

Ядро подмодуля Git является клоном другого репозитория в дереве работы "суперпроекта" *. Git только клонирует полные репозитории. Невозможно клонировать только один подкаталог из существующего репозитория .

* Нормальные подмодули также требуют специальной ссылки в суперпроекте commits/index и (обычно) записи в файле superproject .gitmodules. В несвязаном рабочем дереве можно иметь не отслеживаемые клоны других репозиториев, но такое использование не создает подмодуля.
Git 1.7.0, а позже имеет функцию "редкой проверки", но это не помогло бы переместить каталог lib на верхний уровень каждого клона подмодулей.

Однако вы можете использовать Git поддержку символических ссылок, чтобы сделать что-то довольно близко:

#
# Make the lib directory of each submodule appear in the superproject as
# lib/vendor/packages/$submod_name
#
# With this structure in each of the submodules (a, b, c):
#
#    lib/
#    tests/
#
# We end up with this structure in the superproject:
#
#    lib/
#        vendor/
#            packages/
#                a     (a symlink to ../../../_submodules/a/lib)
#                b     (a symlink to ../../../_submodules/b/lib)
#                c     (a symlink to ../../../_submodules/c/lib)
#    _submodules
#        a/            (a Git submodule)
#            lib/
#            tests/
#        b/            (a Git submodule)
#            lib/
#            tests/
#        c/            (a Git submodule)
#            lib/
#            tests/
#
add_one() {
    dir=lib/vendor/package
    dest="$dir/$1"
    # use fewer ".."s to put the _submodules closer to the symlinks
    s=../../../_submodules/"$1"
    git submodule add "$2" "$dir/$s"
    ln -s "$s"/lib "$dest"
    git add "$dest"
}

cd "$main_repo_toplevel"
mkdir -p lib/vendor/package
add_one a [email protected]:user/package-a.git
add_one b git://public.example.com/work/package-b-dev.git
add_one c ssh://special.example.com/foo.git

Использование Git поддерева

apenwarr git поддерево может отделить и объединить части репозиториев (т.е. отдельные подкаталоги, это оболочка вокруг "сложение поддерева" с другими приятными функциями). Первым шагом будет извлечение истории lib в каждом из ваших подпроектов. Затем либо непосредственно используйте извлеченную историю как подмодуль, либо используйте поддерево Git, чтобы выполнить слияние поддерева в ваш основной репозиторий. В любом случае это обеспечит дополнительный шаг (повторное извлечение истории lib), прежде чем вы сможете интегрировать изменения из подпроекта в основной репозиторий.

Ответ 2

У вас может быть четвертое 'lib' main Git repo, с:

Но эта ссылка полностью не зависит от любого свойства svn: external, которое может быть установлено в зеркальном SVN-репо.

Итак, если у вас уже есть 3 SVN-репозитория, вы можете git-svn их, опубликовать их в GitHub, а затем создать четвертое репо на GitHub, в котором вы добавите эти 3 Git repos в качестве подмодулей, следуя учебник подмодулей (предположим, что у вас есть все 4 репозитория уже на GitHub)

$ mkdir -p lib/vendor/package
$ cd lib/vendor/package
$ for package in a b c d; do
$ git submodule add git://github.com/path/to/$package.git $package
$ done
$ cd ..
$ git commit -m "lib with submodules"
$ git push