在模块化系统上使用版本控制的策略


15

让我们假设(为简单起见)我们有一个具有客户端和服务器功能的应用程序。有一个更好的主意是将一个存储库用于两个或两个单独的存储库?

混合它们可能会更容易跟踪相关的更改并维护相关的分支(即协议演化),但另一方面,会使单个开发更加混乱...


使用单独的分支怎么了?开发人员只需要在本地打开他当前正在工作的分支,因此他什至都不会看到仅在其他分支中的东西。但是,如果他出于某种原因需要进入分支机构,则可以。
Spencer Rathbun

@SpencerRathbun-使用这样的独立分支是灾难的根源。这将是真的很难服务器和客户端,尤其是接口和系统文件等。随着DVCS它会要求你克隆所有客户端和服务器提交之间共享文件,即使你只想要一个,并且不会给你关于哪些客户端和服务器版本可以协同工作的任何提示。与单块(单个)存储库或模块化(多个)存储库故障相比,您实际上遇到了两全其美的情况
Mark Booth

@MarkBooth Humm,我在考虑每个分支中的项目部分,因为他指示它们将共享代码。只需将每个部分标记为适当的分支,就可以了。您的DVCS是否不允许文件/提交具有多个标签?
Spencer Rathbun

Answers:


12

如果您使用的是gitmercurial,则可能需要查看子模块存储库

客户端,服务器及其接口文件将位于其自己的存储库中,但将在超级存储库级别绑定在一起。这将允许您在顶层进行一次检出,git或者hg检出每个子模块/子存储库的适当提交。

仅当客户端和服务器彼此适合时才提交超级存储库,因此超级存储库将只为您提供签出工作系统的选项-因此您将永远不会尝试针对旧版本运行新客户端服务器,反之亦然。

子模块/子存储库为您提供了使用单独存储库的所有优点,以及单个整体存储库的优点,但付出了一些额外的复杂性。

这个答案并不是要提倡githg超越其他SCM,而恰恰是我只足够了解这些 SCM 才知道存在该选项。例如,我不了解svn外部工作原理。


1
现在,这是一个有趣的功能。我很想看一些有关其用法的案例研究,我以前从未听说过它!
艾德·詹姆斯

在颠覆类似的事情是外部定义:svnbook.red-bean.com/en/1.0/ch07s03.html。但是,它的工作方式略有不同。
liori 2011年

1
@MarkBooth:是的,可以。在该页面上,您可以看到类似于-r12345的参数-这些参数定义了您要获取的修订版。而且由于svn:externals属性的版本与任何文本文件一样,因此每个修订版的-r可以具有不同的值。另外,您正在浏览古老的1.0文档。外部定义在1.5中进行了更改,当前版本为1.7。参见:svnbook.red-bean.com/en/1.7/svn.advanced.externals.html
liori 2012年

6

分离!

实际上,我可能会有三个存储库,一个用于客户端库和相应的仅客户端库,一个用于服务器库(以及相应的库),以及一个用于共享库的库(合并了暴露两个库之间功能的API接口) ,以及其他任何共享代码)。我认为这确实是关键,共享代码应放入自己的单独存储库中。这样,您可以确保客户端和服务器之间的互操作性始终处于同一版本,并且与每个使用者的设计隔离。

显然,这并非总是可能的,具体取决于您使用的特定通信框架,但是很可能存在共享代码,这些代码指示数据传输对象的格式或自定义协议(或其他示例)中的握手步骤。 。

假设您有一个相当不错的持续集成和QA设置(根据我的经验,这是一个相当大的假设,但是我还是要做出一个假设。如果您没有QA部门,则至少应获得一些CI),您应该无需使用单仓库模式来防御可能的代码不匹配,您的CI服务器将标记库的互操作性,或者您的质量保证团队将捕获运行时错误(或者,更好的是,您的单元测试也可以)。

拆分存储库的好处在于可以分别对系统的各个部分进行版本控制。是否想要复制上周的服务器并与本周的客户端一起运行,以尝试解决性能问题的根源?别担心。


1

Mercurial中,可以使用此方案,->用于表示子仓库关系:

product -> client -|-> (many components)
                   |->  shared component A

        -> server -|-> (many components)
                   |->  shared component A

产品具有子仓库客户端,服务器。每个子仓库都有它们的组件作为子仓库,可能在两者之间共享至少一个子仓库。

标记可能应该在前两个级别上完成,而不要低于该级别。

提交是在组件级别完成的,超级仓库可以有效地跟踪产品的命名分支和版本。命名分支/书签通常在可用性(即可培训性)和与子存储库的兼容性方面优于克隆分支。

hg倾向于以下假设:超级仓库产品,并且提交是在最高级别完成的,但是当多个产品使用相同的组件时,这种情况就不会特别有效。:-)

我认为如果过渡到git,该方案不会有太大变化,但是我还没有在git中尝试过。


1

这是一个配置管理问题,而不是修订控制问题。与往常一样,程序员使用螺丝刀锤打钉子。弄清楚如何管理配置,修订控件将自行处理。


1

最简单的方法是使用一个单一的储存库,所以除非你像复杂的缘故复杂,那么这应该是默认选择在没有令人信服的理由,否则。

客户和服务器开发是否将由不同的组织进行?客户端(或服务器)是否会有多种实现?客户端开源和服务器实现是秘密的吗?如果所有这些问题的答案都是“否”,那么比单个存储库更复杂的事物可能只会带来不便,而没有任何好处。

如果确实选择维护单独的代码库,则将需要有关如何进行管理的明确策略,以避免不兼容性和依赖性。经过最初的几次打few之后,您可能会发现最安全的事情是始终一起检出两个存储库,一起构建它们,然后一起部署它们……这显然破坏了分离它们的整个目的!

模块化是一个不错的属性,但是拆分存储库并不是实现此目的的工具。正如上一段所暗示的那样,您可以将高度耦合的组件拆分为多个代码库(不希望),同样,您可以在同一代码库内具有高度模块化的组件(希望)。

我多次(成功地)提倡我的团队合并现有的git存储库,因为它简化了开发和部署。


0

暂时忘记存储库。如果您不与任何人共享,您将如何在计算机上组织这两个项目?团队的其他成员将如何做?你会...

  • 将客户端和服务器的所有源文件都放在同一目录中?

  • 创建一个主项目目录,其中包含客户端和服务器的子目录?

  • 将两个项目完全分开?

一旦就团队达成共识,您就可以将项目检入代码存储库。我能想到的所有修订控制工具都乐于再现您喜欢的任何目录结构-它们一点也不关心哪个文件属于哪个项目。除了一个小的管理差异外,拥有一个或两个(或六个)存储库之间的差异通常不会很大。

例如,对于Subversion,客户端和服务器的单独存储库与单个组合存储库之间的最大区别在于修订号的更改方式。使用单一存储库,每次将代码提交到客户端或服务器时,版本号都会增加。使用单独的存储库,对服务器项目的提交不会更改客户端的总修订版号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.