如何设置git子模块

时间:2017-11-07 06:36:41

标签: git git-submodules

方案

我们有一个大项目,在子目录和相互依赖关系中有很多子项目。我们计划外包项目的一部分。

我们的项目结构是这样的 (文本是子文件夹名称):

MAIN
|_Custom
|   |_Source
|   |   |_CustA (Contains multiple projects each in own directory)
|   |   |_CustB (Contains multiple projects each in own directory)
|   |
|   |_Dll
|   |  |_Debug
|   |  |_Release 
|   |
|   |_Lib
|      |_Debug
|      |_Release
|
|_Dll
|   |_Debug
|   |_Release
|
|_Lib
|  |_Debug
|  |_Release
|
|_Plugins
|  |_Dll
|  |  |_Debug
|  |  |_Release
|  |
|  |_Source
|     |_PluginA
|     |_PluginB
|
|_Source
   |_Module1
   |   |_M1A
   |   |_M1B
   |
   |_Module2
       |_M2A

正如我上面提到的,' Custom'部分是我们想要外包的。这些自定义项目依赖于要运行的Main / Custom / Dll,Main / Custom / Lib,Main / Dll,Main / Lib和Main / Plugins / Dll文件夹中的dll和lib文件。这里的问题是,无论根驱动器如何,Main / Dll-Lib和Main / Plugins / Dll文件夹必须在Main文件夹中保持完全相同的层次结构和位置。

也就是说,假设CustA下面有一个项目,它取决于Main的一些dll。 CustA下的所有项目都必须强制设置输出路径  exe和dll文件转到Main / Custom / Dll和lib输出到Main / Custom / Lib。  这些exe(假设它在Release中)必须使用相对路径" ...... \ Dll \ Release"来查找引用的主dll。它将指向Main / Dll / Release文件夹,类似于任何主插件dll。它不能从其他任意设置的路径引用dll或lib。

要求:

当要由我们自己的人克隆Main时,他们必须获取Main下的所有源代码和dll和文件。但是对于Custom,必须创建Main / Custom / Source,Main / Custom / Dll和Main / Custom / Lib文件夹(如果git不允许空文件夹,它们可能包含一些空文件。),但是特定的自定义模块(像CustA及其子目录及其输出exe,dll和lib文件)不得克隆。自定义模块(CustA,CustB,CustC ...)必须根据需要逐个显示/克隆,在Main / Custom / Source文件夹下获取其源代码,并构建以获取其exe-dll-lib文件

另一方面,在外包时,也必须容易设置。 在这里,他们应该能够以这样的方式克隆Main:他们获得Main / Dll,Main / Lib和Main / Plugins / Dll文件夹及其内容exe-dll-lib和其他输出文件,但不是源代码在Main / Source和Main / Plugins / Source中。此外,由于外包将按Custom模块完成,假设此开发人员已被分配CustA,他必须能够轻松获取CustA下所有项目的源代码,但必须无法克隆/拉自定义/源极/ CustB。

我已尝试过的内容:

整个Main及其内部的所有内容当前都备份到我们自己的服务器计算机上的SVN存储库中。但我们正在寻求迁移到git,和 使用Nulabs-backlog进行项目问题跟踪和管理。

我做了一些研究并使用虚拟文件创建了我们项目结构的副本,并且能够创建一个包含所有文件和子文件夹的所有(我的意思是ALL)的测试存储库,但这不允许像我上面提到的限制访问

据我所知,我可以将整个项目划分为多个较小的存储库,然后使用git子模块功能引用其他存储库下的特定存储库。所以我从Main / Plugins / Source,Main / Source和自定义模块创建了单独的存储库,为Main / Custom / Source / CustA,Main / Custom / Source / CustB,Main / Custom / Source / CustC等创建了单独的存储库。并将它们上传到远程。然后我为Main文件夹本身创建了一个存储库,并为此添加了Main / Dll,Main / Lib,Main / Plugins / Dll文件夹。这里,#/ Source模块显示为子模块,起初看起来还可以。当我将这个主回购推送到远程时,远程也显示CustA,CustB ...,Main / Source,Main / Plugins / Source等是子模块,而Dll和Lib文件夹显示正确的文件。

但我无法理解如何正确克隆这些。

问题:

当我从远程克隆Main repo时,克隆会重新创建源文件夹,其中源文件夹不包含任何内容,因为它们是子模块,而Dll和Lib文件夹已正确填充。但是当我尝试显式拉出Main / Source或Main / Plugins / Source文件夹时,它不起作用。它既不允许我设置源文件夹的远程路径,因为这些文件夹本身是主repo的一部分,也不允许我在删除这些空源文件夹时执行Pull,然后重新创建它们并设置它们远程路径,以反映实际的子模块repo URL。

分区我做错了吗?或者克隆步骤错了吗?如果是这样,我如何正确设置git以满足上述要求?

1 个答案:

答案 0 :(得分:1)

最后,我设法通过大量的谷歌搜索以及我在SO上发现的其他想法来弄清楚。

我选择了一个简单直接的Git工作树。 基本上,我将整个项目结构分为三个部分。

第1部分:存储实际的文件夹 - 子文件夹结构以及Dll,pdb,lib和头文件。这些文件是开发“Custom”部分以及“Main”应用程序本身所必需的。因此,这个回购允许访问我们的本地团队以及外包团队。

第2部分:存储与“Main”应用程序本身的开发相关的实际代码(cpp)和csproj,sln及相关文件。此回购只允许访问我们自己的本地团队。

第3部分:存储“自定义”模块。这些模块是分开的,每个模块(CustA,CustB,CustC ......)都有自己的仓库。我们的当地团队可以访问所有这些回购。外包团队只能访问包含已分配给它的模块的仓库。

这些回购中的每一个都有一个主人和一个'发展'分支。实际开发在从“Develop”分支派生的自定义分支上完成,并在完全完成时合并。 'Develop'分支将在每个Release上同步到master,以便master分支始终只包含稳定的'Release'代码。

我编写了2个简单的bash脚本,以便轻松设置开发回购。

本地团队的脚本要求提供根文件夹,自定义模块的名称(如果正在开发自定义模块)和自定义模块仓库的URL(如果正在开发自定义模块)。然后它在运行它的本地机器上创建一个空的Git仓库,拉出所有开发场景所需的'Part 1'仓库,继续将'Part 2'仓库拉到正确的文件夹中。如果提供了自定义模块名称和URL,它将继续引入“第3部分”的相应仓库。 接下来,由于“Part 1”repo通常不会被修改,为了防止意外提交或推送,脚本导航到其根文件夹,并将“.git”重命名为其他内容,以便Part 1 repo充当repo不再。当您需要更改或更新此repo时,您需要将文件夹显式重命名为'.git'拉/同步以使其达到最新版本,然后执行更改并推送。当然,有一个很小的问题,在完成之后,我们需要记住将'.git'文件夹重命名为其他内容,并注意在推送代码时将正确的头文件推送到第1部分。第2部分。

“Part 2”repo和任何“Part 3”repos将自动切换到“Develop”分支,并从本地计算机中删除master分支。当然,只要我们与遥控器同步,主分支就会被带回来。

如果是外包团队,脚本将不会拉出“第2部分”回购。它将专门要求一个根文件夹和一个自定义模块名称和URL,设置'Part 1'和'Part 3'repos,重命名'Part 1'repo的'.git'文件夹,切换到Develop分支'Part 3',如果一个分支名称也作为参数传递给脚本,将从Develop派生一个新分支并切换到这个新分支。同样,在此之前,我们将在向外包团队提交/推送之前提供指导或规则,以便他们知道如何以及何时重新拉出“第1部分”回购,以及记住不要提交/推送到“第1部分”,以及其他要遵循的规则。