我想知道Git子模块是否是我目前保留在RCS下的某些代码的合适组织,如果是,那么子模块应该如何组织。
假设我有一个库模块的集合(可能是库,可能是单个库的一部分;这是一个可供讨论的项目)。假设其中一些模块是基础模块,其他模块依赖于基础模块。所有这些模块都打算被其他打包的软件(程序)使用,这些软件可能包括适当选择这些软件包作为子模块。
为了使其具体化,库模块是:
stderr
- 标准化的错误报告例程(不依赖于其他模块)。filter
- 文件过滤程序(如grep
或cat
):使用stderr
。debug
- 调试跟踪支持:使用stderr
phasedtest
- 单位代码测试:直接使用filter
,debug
和stderr
。rational
- 一个有理数运算包,它使用phasedtest
作为其测试代码,但是它独立于phasedtest
及其依赖项。许多其他程序使用stderr
。相当多的使用也使用filter
(并且所有使用filter
的代码也直接使用stderr
),但是有相当多的程序使用stderr
但不使用filter
。有些程序使用debug
;基本上所有这些程序也直接使用stderr
,但它们可能会也可能不会直接使用filter
。使用phasedtest
的单元测试程序可能会也可能不会直接使用stderr
,filter
和debug
(他们更可能使用stderr
而不是其他人),但phasedtest
本身需要它们,因此这些程序总是间接使用这些模块。有些程序可能会使用rational
;通常他们也会使用stderr
(我写的几乎所有东西都使用stderr
),但这些程序一般不直接使用phasedtest
。
只是为了澄清:目前,这些潜在的Git模块和子模块根本不在Git中;他们中的大多数在RCS(在Y2K之前的SCCS)中拥有广泛的(10 - 30年)历史,当它们转换为Git时将被保留。目的是在适当的时候将所有的回购都放到GitHub中。通常,这些模块都相当稳定。它们确实得到修订或扩展,但不一定每年都有。有时,三年或更长时间没有改变其中一些。我有一个构建/分发系统,其中构成可能成为子模块的文件在准备发布时被拉入更大程序的分发中。在正常(单人)开发期间,材料存在于一个库中,其中有数百个源文件内置于单个(静态)库(在$HOME/lib
中)和单个头文件目录($HOME/inc
,类似于,但完全独立于/usr/include
或/usr/local/include
)。
我正在寻求让结构“正确” - 足够正确,我不会后悔我所做的 - 在将它们转换为Git之前。我仍然需要解决版本标记和标记问题;这是一个完全独立的袋子,而不是这个问题的一部分。
根据我对子模块的理解,看起来:
stderr
应该在自己的存储库中。filter
应该在stderr
作为子模块的自己的存储库中。debug
应该在stderr
作为子模块的自己的存储库中。phasedtest
应该在自己的存储库中:
debug
作为一个子模块
filter
作为一个子模块
但它是否应该包括stderr
作为直接子模块,或者它应该使用嵌套子模块中的stderr
版本(stderr
内部的debug
和/或stderr
内部的filter
)?rational
应该在自己的存储库中,phasedtest
作为子模块(以及phasedtest
随附的子模块组织)。filter
和debug
都需要stderr
子模块(但它们不太可能在任何特定版本的stderr
上显着依赖 - 几乎任何版本10级的工作版本就足够了)。因此,他们都需要在子模块中使用stderr
版本。libstderr
,libdebug
和libfilter
?
或者libfilter
应该包括来自stderr
的材料,libdebug
是否应该包括来自stderr
(两个图书馆)的材料?
或者应该有一个单独的复合库libjlss
与stderr
,debug
和filter
元素?
如果共享库而不是静态库,答案是否会有所不同?phasedtest
代码组织为第四个库,其中包含模块stderr
,filter
和debug
作为子模块(因此stderr
将出现三次,一次作为直接依赖,两次作为debug
和filter
的依赖),或者它应该是需要与三个独立的依赖库链接的小型库?rational
模块只需要phasedtest
进行测试,因此不会安装phasedtest
库或库。但它需要它们进行测试。它是否需要预先安装的phasedtest
库(库),还是应该是自包含的并且具有必要的测试代码作为其分发的一部分?rational
的程序也可能使用stderr
(可能会),但可能会或可能不会使用debug
和filter
,除了单元测试自己的组件外,不太可能使用phasedtest
。你的前两个问题(“git子模块是否合适?”和“我应该如何组织它们?”)并不适合stackoverflow:答案主要是意见问题,而且很难识别任何单一的答案都是“正确的”。
您的辅助问题稍微更易于解决:
存储库是否有最小的合理大小?
不是,不是。
单个存储库是否存在最大数量的子模块?
同样,不,但在创建包含数百个子模块的怪物存储库之前,请确保您首先熟悉它们。人们对如何最好地管理子模块有不同的看法。 Here is one person花了一些时间思考。我不同意他的所有想法,但它至少是一种开始思考这个问题的方法。
如果单个子模块是单个存储库使用的多个子模块的子子模块,这是否重要?
不是真的,不,虽然如果你的源有多个存储库实例,你可能会遇到版本偏差的问题(例如,一个是版本A而另一个是版本B而另一个是版本C)除非你非常小心。
子模块是否有传统的目录结构?所有目录直接位于顶级目录中,或者根目录中的标准目录名中的某些目录,还是超级项目目录层次结构中的准随机位置?
没有,但通常你会选择适合你的东西并坚持下去。我见过很多将子模块放入lib
或modules
目录的项目,而其他项目则将它们放在顶层。
我有没有发现任何明显的陷阱?
请记住,当作为子模块签出时,当前HEAD由父存储库管理。也就是说,如果你将cd
转换为子模块,进行更改,推送它们,然后在父项目中运行git submodule update
,则会将子模块的本地副本回滚到父项中记录的任何提交。
出于这个原因,我通常将子模块视为存储库的只读实例,该存储库只能通过运行git pull
(后跟父存储库中的后续提交)进行更新。我只编辑存储库的独立签出中的文件。
在将新更改提取到父存储库之后,您需要训练自己定期运行git submodule update
(如果这些更改包含子模块的新版本)。
在我看来,你有3个选项子模块,子树或依赖项(预构建的静态库)。我最近一直在使用子模块,这是一种将git repos放在git repo中的方法,并跟踪你的根目录所使用的子模块repo的提交。如果需要在子模块中进行更改,则应使用子模块,否则请使用子树或依赖项。
要使用依赖项,您需要某种可以打包和解析依赖项的工具 - 依赖项管理器。有一些,但我还没有发现任何人是一般的,而不是嵌套的构建工具。