29

我在源代码控制下有一个大型代码库(以前是颠覆,现在是 git)。为了编译代码并运行测试,我使用了一组 3rd 方库。这些库可以分为几类L

  • 仅限二进制文件
  • 第三方来源
  • 3rd 方来源 + 本地修改

每个库都有其 {Windows, Linux} X {debug, release} X {32bit, 64bit} 配置。此外,这些库随着时间的推移而发展,我的项目的不同版本使用这些库的不同版本/构建。

我的问题是存储这些第 3 方的最佳方式是什么?

这是我的一组偏好:

  1. 保持项目源存储库的大小较小
  2. 使项目源与第 3 方保持同步,以便我始终可以编译和运行旧版本
  3. 易于管理
  4. 跨平台

我尝试并想到了几种解决方案,但都不令人满意:

  1. 使用版本控制脚本从手动管理的 ftp 服务器获取二进制文件,该服务器包含所有版本的库。这可行,但需要仔细管理服务器上的目录结构。这很容易出错,因为有人可能会用新版本覆盖其中一个二进制文件。
  2. SVN externals - 当时 SVN externals 无法引用特定标签。今天我正在使用 git。
  3. Git 子模块 - 拉取可能很大的整个外部存储库。或者,它需要为每个库管理一个单独的存储库。子模块指向一个特定的标签,这意味着要么我得到所有的外部,当我只需要一些时,要么我在 git 树中模仿一些奇怪的文件系统。

我很清楚,第 3 方源代码需要存储在供应商分支的 git 中,但二进制文件和标头是另一回事。

4

3 回答 3

13

我的问题的一个公平解决方案是最近合并到主线 git中的git-subtree 。它在我的要求和平台限制之间提供了一个公平的平衡。现在我有多个外部存储库(每个都有一个供应商分支和本地更改分支),每个项目存储库都将这些外部存储的一部分放入子文件夹中。为了使事情井井有条,我维护了一个“bin”和“lib”文件夹,其中包含指向 externals 子文件夹中相应文件/文件夹的软链接。

git-subtree 允许将外部存储库中的子树合并到子文件夹中。子文件夹可以与外部存储库来回合并。

优点缺点:

  1. 小型存储库 - 存储库没有我希望的那么小,但它仅包含来自外部存储库的必要部分。为了节省空间,我尽量保持外部树木很小。我认为这是一个很好的代价,作为回报,我得到了简单性和健壮性;因为加载和更新项目是一个简单的 git pull 并且所有项目相关数据都包含在一个存储库中

  2. 项目/外部同步 - 由于项目和外部在同一个存储库中进行版本控制,我可以签出我想要的任何分支/标签,并期望它能够正常工作。

  3. 简单 - 日常工作是直截了当的。更新外部存储库、创建新存储库或切换到不同版本的外部存储库可能会很棘手,并且需要特殊的语法。然而,这确实发生得太多了。最好的事情是可以先向这个项目添加一个新的外部,然后才将它(使用 git-subtree)拆分到它自己的存储库中。

  4. 跨平台 - 嗯,它是 git

  5. 二进制文件 - 我决定避免持有二进制文件,而是提供 Makefile。我做出这个决定是因为我的一些外部依赖于其他外部,这使得构建一个不经常更改的二进制文件变得非常困难。对于某些外部组件,由于构建时间非常长,我确实存储了二进制文件。

结构:

/root
   /External
      /External1 (git-subtree from git@git.domain.com:External1 v1.0)
      /External2 (git-subtree from git@git.domain.com:External2 v0.7)
   /lib
      /libExternal1.a -> ../External/External1/libExternal1.a
      /libExternal2.a -> ../External/External1/libExternal2.a
   /include
      /External1 -> ../External/External1/include
      /External2 -> ../External/External2/include
于 2012-07-13T07:36:49.963 回答
0

我们已经选择了您的选项 3 的变体。选项 1 在我看来等同于选项 3,但您需要更多的实施/测试工作,因此更有可能出错。

最终,如果您希望能够准确地重新创建构建,您需要将您的外部(包括二进制文件)与代码本身一起进行版本控制并在本地托管。并且 git 子模块会很好地为你做这件事。

于 2012-07-03T20:38:13.630 回答
0

对于第三方来源,我认为子模块正是您正在寻找的。如果您不想在每个克隆中都需要整个上游历史记录,请使用您自己的上游存储库前端,其中包含一个仅包含必要历史记录的手工分支。看看git commit-tree如何制作这些,这很容易。提交 id 不会匹配权威上游,但树 id 会。

对于二进制文件,git 附件似乎是最推荐的存储与 git 的源差异焦点不相符的内容的方式。我自己没有使用过它,但该设计看起来已准备好用于生产,它还支持多个独立的“存储库”,并且看起来尽可能方便。

这不是交钥匙,所以它并不能真正满足您的第三个要求,但它可以解决剩下的问题,您需要的是直接使用基本工具。

于 2012-07-07T19:41:47.857 回答