Git 管理源代码管理下代码使用的第三方源代码和二进制文件

Git 管理源代码管理下代码使用的第三方源代码和二进制文件,git,git-submodules,git-subtree,Git,Git Submodules,Git Subtree,我有一个很大的源代码库(以前是subversion,现在是git)。为了编译代码并运行测试,我使用了一组第三方库。这些库可以分为几个类别 仅二进制文件 第三方来源 第三方来源+本地修改 每个库都有其{Windows,Linux}X{debug,release}X{32位,64位}配置。此外,这些库随着时间的推移而发展,我的项目的不同版本使用这些库的不同版本/构建 我的问题是存储这些第三方的最佳方式是什么? 以下是我的一组首选项: 使项目源存储库的大小保持较小 保持项目源代码与第三方同步,以便

我有一个很大的源代码库(以前是subversion,现在是git)。为了编译代码并运行测试,我使用了一组第三方库。这些库可以分为几个类别

  • 仅二进制文件
  • 第三方来源
  • 第三方来源+本地修改
每个库都有其{Windows,Linux}X{debug,release}X{32位,64位}配置。此外,这些库随着时间的推移而发展,我的项目的不同版本使用这些库的不同版本/构建

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

以下是我的一组首选项:

  • 使项目源存储库的大小保持较小
  • 保持项目源代码与第三方同步,以便我可以始终编译和运行旧版本
  • 易于管理
  • 跨平台
  • 我尝试并思考了几种解决方案,但都不令人满意:

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

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

    我们选择了选项3的变体。在我看来,选项1相当于选项3,但您需要更多的实现/测试工作,因此出错的可能性更大


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

    对于第三方来源,我认为子模块正是您所需要的。如果您不想在每个克隆中都要求完整的上游历史记录,请使用您自己的前端回购,其中包含一个手工制作的分支,其中只包含必要的历史记录。查看git提交树,看看如何实现这些,很简单。提交id与权威上游不匹配,但树id将匹配

    对于二进制文件,git附件似乎是最推荐的存储内容的方法,这些内容不适合git的源代码差异焦点。我自己还没有使用过它,但它的设计看起来已经可以投入生产使用了,它还支持多个独立的存储库,并且看起来尽可能的方便


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

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

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

    优点/缺点:

  • 小型存储库—存储库没有我希望的那么小,但它只包含外部存储库中必要的部分。为了节省空间,我尽量保持外部树木的小。我认为这是一个很好的价格回报,当我得到简单性和稳健性;因为加载和更新项目是一个简单的git拉动,所有与项目相关的数据都包含在一个存储库中

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

  • 简单-每天的工作都很简单。更新外部存储库、创建新的存储库或切换到外部存储库的不同版本可能很棘手,需要特殊的语法。然而,这种情况确实发生得太多了。最好的情况是,可以先向该项目添加一个新的外部文件,然后再将其拆分(使用git子树)到自己的存储库中

  • 跨平台-是git

  • 二进制文件-我决定避免保存二进制文件,而是提供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
    

    外部是否使用了多个子模块?如果没有,你是如何组织这棵树的。我正在考虑一个场景,不同的项目需要不同的库版本组合。外部有多个子模块。你对此有什么特别的担心吗?我担心的是我需要支持~20个外部存储库,包括所有涉及的配置、用户访问等。否则这似乎是正确的做法。好的。20是一个相当大的数字。我们目前每个项目大约有四个。但是有几个子模块有一组库,我们希望这些库需要一起更新。这听起来不适合你。我不确定其他的选择听起来有多少