假设我有 3 个 git 存储库,每个存储库在根目录中都有一个 lib
和 tests
文件夹.所有 3 个存储库都是我希望成为单个包的一部分,但是将存储库分开对我来说很重要.
Let's say I have 3 git repositories, each with a lib
and tests
folder in the root. All 3 repositories are part of what I want to be a single package, however it is important to me to keep the repositories separate.
我是来自 svn 的 git 新手,所以我一直在阅读 submodules
以及它们与 svn:externals
的区别.在 SVN 中,我可以有一个
I am new to git coming from svn, so I have been reading up on submodules
and how they differ from svn:externals
. In SVN I could have a single
lib/vendor/package
目录,在 package
内部,我可以设置 3 个外部文件,指向我的 3 个存储库中的每一个 lib
目录,将其适当重命名为
directory, and inside package
I could setup 3 externals pointing to each of my 3 repositories lib
directory, renaming it appropriately like
lib/vendor/package/a -> repo1/lib
lib/vendor/package/b -> repo2/lib
lib/vendor/package/c -> repo3/lib
但据我所知,这在 git 中是不可能的.我错过了什么吗?
but from my understanding this is not possible with git. Am I missing something?
我真的希望这可以通过两种方式之一解决.
Really I'm hoping this can be solved in one of two ways.
a
、b
, 和 c
文件夹内的根目录)svn:externals
结合 githubs svn 支持进行设置,引用每个 git 存储库中的 lib
目录(根据我的理解不可能)a
, b
, and c
folder inside the root)svn:externals
in combination with githubs svn support, referencing the lib
directory within each git repository (from my understanding this is impossible)我实际上曾尝试按照您链接的子模块教程进行操作,但遇到了以下问题.
I had actually tried to follow the submodules tutorial you linked to, but I run into the following problem.
做如上图所示的事情,而不是像这样的映射
Doing things as shown above, instead of a mapping like
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
这并不理想,因为现在访问repo1
的lib
文件夹中的ClassA
,路径是
this is not ideal since now to access ClassA
inside repo1
's lib
folder, the path is
lib/vendor/package/a/lib/ClassA
当我真的想得到(这可以通过 svn:externals 实现)
when I'm really trying to get (and this is possible with svn:externals)
lib/vendor/package/a/ClassA
因为上面的a
实际上是repo1/lib
,而不是repo1
的根目录.
since a
above is actually repo1/lib
, and not the root directory of repo1
.
这样的事情很重要,因为以 PHP5.3
为例,使用 SplClassLoader
( http://gist.github.com/221634 ),它需要一个命名空间到目录的映射,如
Something like this is important since, with PHP5.3
for example, using the SplClassLoader
( http://gist.github.com/221634 ), it requires a namespace-to-directory mapping like
PackageaClassA -> lib/vendor/package/a/ClassA
这是我概念性误解的地方,如何设置第 4 个 git 存储库以允许我的目录映射如上.
this is where my conceptual misunderstanding is, how to setup that 4th git repository to allow my directory mappings like above.
你说得对,Git 子模块不能直接做你想做的事.它在 SVN 中工作,因为存储库的根、分支及其任何子目录都是同一种对象.在 Git 中,存储库、分支和目录都是不同类型的对象(您不能将目录用作完整存储库或分支).
You are right, Git submodules can not directly do exactly what you want. It works in SVN because the root of a repository, branches, and any subdirectory thereof are the same kind of object. In Git, a repository, a branch, and a directory are all distinct kinds of objects (you can not use a directory as a full repository or as a branch).
不过,有几种间接方法可以实现您的愿望.
There are a couple of indirect ways to accomplish what you want though.
Git 子模块的核心是超级项目"的工作树中另一个存储库的克隆*.Git 只克隆完整的存储库.不可能从现有存储库中只克隆一个子目录.
The core of a Git submodule is a clone of another repository in the work tree of the "superproject"*. Git only clones full repositories. It is not possible to clone just a single subdirectory out of an existing repository.
* 普通子模块还需要在超级项目的提交/索引和(通常)超级项目的 .gitmodules
文件中的一个特殊引用.在不相关的工作树中可能有其他存储库的非跟踪克隆,但这种用法不会创建子模块.
Git 1.7.0 及更高版本具有稀疏检出"功能,但将 lib
目录重新定位到每个子模块克隆的顶级目录无济于事.
* Normal submodules also require a special reference in the superproject's commits/index and (normally) an entry in the superproject's .gitmodules
file.
It is possible to have non-tracked clones of other repositories in an unrelated working tree, but such usage does not create a submodule.
Git 1.7.0 and later has a "sparse checkout" feature, but it would not help to relocate the lib
directory the top level of each submodule clone.
然而,您可能能够使用 Git 对符号链接的支持来做一些相当接近的事情:
You might, however be able to use Git's support for symbolic links to do something that is fairly close:
#
# 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 可以拆分和合并部分存储库(即单个子目录;它是 子树合并" 与其他不错的功能).第一步是提取每个子项目中 lib
的历史记录.然后,要么直接使用提取的历史作为子模块,要么使用 git subtree 将子树合并到您的主存储库中.无论哪种方式,这都会引入一个额外的步骤(重新提取 lib
历史记录),然后才能将子项目的更改集成到主存储库中.
apenwarr's git subtree can split off and merge parts of repositories (i.e. individual subdirectories; it is a wrapper around "subtree merging" with other nice features). The first step would be to extract the history of lib
in each of your sub-projects. Then, either directly use the extracted history as a submodule, or use git subtree to do a subtree merge into your main repository. Either way, this would introduce an extra step (re-extracting the lib
history) before you could integrate changes from a sub-project into your main repository.
这篇关于git 子模块 svn 外部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!