【问题标题】:Best practices for multiple git repositories多个 git 存储库的最佳实践
【发布时间】:2015-09-21 14:15:45
【问题描述】:

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

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

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

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

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

对于b,可能需要其他内容,例如a v0.9 和c 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-submodules、git-subtree、google 的 git-repo、 git-slave等

对于如此复杂的项目,我该如何管理持续集成?

编辑

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

【问题讨论】:

  • 我实际上不鼓励这样的架构。拥有这样的存储库只会让维护者感到困惑,而且测试确实应该按项目进行。
  • 上面的各个文件夹是不同的 .git 存储库,而不是一个单一的大存储库 - 否则它们不能有不同的分支和标签。
  • 真正的问题是如何在不模拟所有其他依赖项目的情况下运行测试?特别是当所有项目可能使用不同的版本时。

标签: git git-submodules git-subtree git-repo git-slave


【解决方案1】:

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


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

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

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

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

想要在路径 foo 处检查正确的提交吗?

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

rev-parse 从索引中获取 foo 的内容 id,cd 和 checkout 会这样做。

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

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 完成,我将把它留给其他人解决。

【讨论】:

  • 很好的答案。如何在不重复 superproject 子模块的情况下跟踪版本依赖关系?项目a 需要特定版本的b。我可以将该约束设置为a 本身的一部分吗?
  • 啊,好吧,我要带我的孩子去露营,之前的评论有点仓促。是的,您可以通过这种方式来完成您的依赖——为此,没有子模块小工具,但它又是一个近乎单一的工具——添加一个实际驻留在其他地方的子模块,你去其他地方并说git config worktree .. 来确定工作树位置并在工作树中使用它而不是您进行初始子模块更新echo gitdir: /path/to/projecta/.git &gt;$theprojectbpath_in_a。玩玩吧,也许明天我会有更多的时间。
【解决方案2】:

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

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

正如 jthill 所说,持续集成与如何处理项目的问题非常相似。

【讨论】:

  • 不,我不能在子模块(从库)中强制使用公共分支/标签。 gits 似乎比我想要实现的更复杂,但会试一试。谢谢:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-19
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
  • 2023-04-08
  • 2011-03-23
相关资源
最近更新 更多