git submodule svn external

时间:2010-05-21 03:35:32

标签: php svn git

假设我有3个git存储库,每个存储库在根目录中都有一个libtests文件夹。所有3个存储库都是我想成为单个软件包的一部分,但是对我来说保持存储库是分开的很重要。

我是来自svn的git的新手,所以我一直在阅读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是不可能的。我错过了什么吗?

我真的希望这可以通过两种方式解决。

  1. 有人会指出如何创建第4个git存储库,其中包含其他3个如上所述组织的子模块(我可以在其中ab和{{1}根目录中的文件夹)
  2. 有人会指出如何使用c结合githubs svn支持来设置它,引用每个git存储库中的svn:externals目录(根据我的理解,这是不可能的)
  3. 更新

    我实际上已经尝试按照您链接的子模块教程,但我遇到了以下问题。

    执行上面显示的操作,而不是像

    这样的映射
    lib

    我留下了

    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 的{​​{1}}文件夹中的ClassA,路径是

    repo1

    当我真的想要获得(这可能是svn:externals)

    lib

    因为上面的lib/vendor/package/a/lib/ClassA 实际上是lib/vendor/package/a/ClassA ,而不是a的根目录。

    这样的事情非常重要,因为repo1/lib使用repo1http://gist.github.com/221634),它需要一个名称空间到目录的映射,例如

    PHP5.3

    这是我的概念误解,如何设置第4个git存储库以允许我的目录映射如上所述。

2 个答案:

答案 0 :(得分:3)

你是对的,Git子模块不能直接做你想要的。它在SVN中工作,因为存储库的根,分支及其任何子目录都是同一种对象。在Git中,存储库,分支和目录都是不同类型的对象(您不能将目录用作完整存储库或分支)。

虽然有几种间接的方法可以达到你想要的效果。

使用子模块和符号链接

Git子模块的核心是“superproject” * 工作树中另一个存储库的克隆。 Git只克隆完整的存储库。无法从现有存储库中仅克隆单个子目录。

* 正常子模块还需要超级项目的提交/索引中的特殊引用,以及(通常)超级项目的.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 git@githost.example.com: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 subtree可以拆分并合并部分存储库(即单个子目录;它是“subtree merging”的包装器,具有其他不错的功能)。第一步是在每个子项目中提取lib的历史记录。然后,直接将提取的历史记录用作子模块,或使用 git subtree 将子树合并到主存储库中。无论哪种方式,这都会引入一个额外的步骤(重新提取lib历史记录),然后才能将子项目中的更改集成到主存储库中。

答案 1 :(得分:0)

你可以拥有一个'lib'主Git仓库,其中包括:

但是这个引用完全独立于你在镜像SVN仓库中设置的任何'svn:external'属性。

因此,如果你已经有3个SVN repos,你可以git-svn,在GitHub上发布它们,然后在GitHub上创建第四个repo,你将在{{{{{{{ 3}}(假设你在GitHub上已经有4个repos)

$ 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