多个 git 个存储库的最佳做法

Best practices for multiple git repositories

我有大约 20 个不同的存储库。许多是独立的并编译为库,但其他一些在它们之间具有依赖关系。依赖解析和分支很复杂。

假设我有一个超级项目,它只聚合所有其他存储库。它专门用于 运行 测试——这里没有真正的开发。

/superproject  [master, HEAD]
    /a         [master, HEAD]
    /b         [master, HEAD]
    /c         [master, HEAD]
    /...

现在,为每个功能开发特定功能或修复 (a),尤其是那些需要特定版本的项目才能编译或 运行(b v2.0c 3.0) 我必须创建一个新分支:

/superproject  [branch-a, HEAD]  <-- branch for 'a' project
    /a         [master]  <-- new commits here
    /b         [v2.0]
    /c         [v3.0]

对于 b,可能还需要其他内容,例如 a v0.9c v3.1:

/superproject  [branch-b, HEAD]  <-- branch for 'b' project
    /a         [v0.9]   <-- older version than 'a'
    /b         [master] <-- new commits go here
    /c         [v3.1]   <-- newer version than 'a'

在实现涉及功能分支、修补程序分支、发布分支等的常见 git 工作流时,这变得更加复杂和复杂。我被建议(也被反对)使用 git-submodulesgit-subtree、google的git-repogit-slave

对于这样一个复杂的项目,我如何管理持续集成

编辑

真正的问题是如何 运行 测试而不必模拟所有其他依赖项目?特别是当所有项目可能使用不同的版本时。 Trigger Jenkins tests after commits in git submodules

要并行处理多个分支,请尽可能使用并行克隆。 cd 比结帐、清理、检查陈旧碎屑和重新创建缓存要容易得多。


就记录您的测试环境而言,您所描述的正是子模块所做的每一个细节。对于这么简单的事情,我建议您完全不使用 submodule 命令进行设置,并在您感到舒服后告诉它您的设置,并且子模块问题列表中的第一项是击键次数。

从您问题中的设置开始,以下是您如何设置自己以在子项目中记录干净的构建:

cd $superproject
git init .
git add a b c etc
git commit -m "recording test state for $thistest"

就是这样。您已经提交了一个提交 ID 列表,即每个存储库中当前签出的提交的 ID。实际内容在那些回购协议中,而不是这个,但就 git 而言,这就是文件和子模块之间的全部区别。 .gitmodules 文件有帮助克隆者的随机注释,主要是一个应该包含必要提交的建议回购,以及命令默认值的随机注释,但它所做的很简单明了。

想检查路径 foo 上的正确提交吗?

(commit=`git rev-parse :foo`; cd foo; git checkout $commit)

rev-parse 从索引中获取 foo 的内容 ID,cd 和 checkout 会执行此操作。

以下是您如何找到所有子模块以及应该检查哪些内容以重新创建阶段性索引环境:

git ls-files -s | grep ^16

检查子模块的当前索引列表以及实际检查的内容:

echo $(git rev-parse :$submodule; (cd $submodule; git rev-parse HEAD))

好了。检查所有子模块中的正确提交?

git ls-files -s | grep ^16 | while read mode commit stage path; do
        (cd "$path"; git checkout $commit)
done

有时您携带要应用到每次结帐的本地补丁:

git ls-files -s | grep ^16 | while read mode commit stage path; do
        (cd $path; git rebase $commit)
done

等等。这些有 git submodule 命令,但它们不会做您在上面看不到的任何事情。其他人都一样,你可以将他们所做的一切翻译成像上面那样的近乎单行的内容。

子模块没有什么神秘的。


持续集成通常由 any of a whole lot of tools 完成,我会把它留给其他人解决。

作为作者,git slave可以在这种情况下工作。如何使用它取决于你是否控制了reposabc;我的意思是你可以使分支策略在它们之间同步,这样 v2 分支对每个人都意味着同样的事情。如果这是真的,我强烈建议 git slave 因为您基本上可以将其视为一个大项目。

如果您不能强制执行一个通用的分支和标记策略,那么您可以强加一个,它越来越倾向于 jthill 在 git submodules 中建议的工作流的轻量级版本。具体来说,您可以拥有自己的回购跟踪 a bc 并在每个回购中创建一个 branch a 分支,这将对应于每个从属回购的任何正确分支是。就像 git submodules 你必须手动更新每个 repo(在这种情况下合并)。但是,您不需要执行在超级项目中进行提交的 mother-may-I 步骤。使用这种技术不是让从属项目在自己开发时共享相同分支名称的灌篮用例,但它会起作用。

正如 jthill 所说,持续集成与如何处理项目的问题几乎是正交的。