假设我有3个git存储库,每个存储库在根目录中都有一个lib
和tests
文件夹。所有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是不可能的。我错过了什么吗?
我真的希望这可以通过两种方式解决。
a
,b
和{{1}根目录中的文件夹)c
结合githubs svn支持来设置它,引用每个git存储库中的svn:externals
目录(根据我的理解,这是不可能的)我实际上已经尝试按照您链接的子模块教程,但我遇到了以下问题。
执行上面显示的操作,而不是像
这样的映射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
使用repo1
(http://gist.github.com/221634),它需要一个名称空间到目录的映射,例如
PHP5.3
这是我的概念误解,如何设置第4个git存储库以允许我的目录映射如上所述。
答案 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
apenwarr的git subtree可以拆分并合并部分存储库(即单个子目录;它是“subtree merging”的包装器,具有其他不错的功能)。第一步是在每个子项目中提取lib
的历史记录。然后,直接将提取的历史记录用作子模块,或使用 git subtree 将子树合并到主存储库中。无论哪种方式,这都会引入一个额外的步骤(重新提取lib
历史记录),然后才能将子项目中的更改集成到主存储库中。
答案 1 :(得分:0)
你可以拥有一个'lib'主Git仓库,其中包括:
lib/vendor/package
内容但是这个引用完全独立于你在镜像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