Java jar文件到存储库(CVS,SVN ..)

为什么将Java jar文件提交到存储库(CVS,SVN ..)是一个坏主意

因为您可以从源重建它们。 如果您正在讨论项目所需的第三方JAR文件,那么最好将它们提交到存储库中,以便项目是自包含的。

所以,你有一个使用一些外部依赖项的项目。 这种依赖性是众所周知的。 他们都有

  • 一个组(通常是组织/伪造创建它们)
  • 标识符(他们的名字)
  • 厌恶

在maven术语中,这些信息称为工件(Jar)坐标。

我所讨论的依赖关系是内部的(对于Web应用程序,它可以是您的服​​务/域层)或外部(log4j,jdbc驱动程序,Java EE框架,您的名字,……)。 所有这些依赖项(也称为工件)实际上是最低级别的二进制文件(JAR / WAR / EAR),您的CVS / SVN / GIT将无法有效存储。 实际上,SCM使用的是版本化内容(diff操作最有效的内容)仅为文本的假设。 因此,当存储二进制数据时,它们很少是存储优化(与文本相反,其中仅存储版本差异)。

因此,我倾向于建议你使用依赖管理构建系统,如maven , Ivy或Gradle 。 使用这样的工具,您将在文本(或XML)文件中声明所有依赖项(实际上,在此文件中,您将声明依赖项的工件坐标),该文件将在您的SCM中。 但您的依赖关系不会出现在SCM中。 相反,每个开发人员都会在其开发机器上下载它们。

这将一些网络负载从SCM服务器传输到互联网(带宽通常比内部企业网络更受限制),并询问工件的长期可用性问题。 这两个答案都得到了解决(至少在amven工作中,但我相信常春藤和gradle都可以使用企业代理,如Nexus , Artifactory和连接到这些工具 – 而且似乎有一些关于这个问题的问题)。其他。

这些工具的优点在于它们在内部网络中提供了所有必需工件的视图,只要允许您在这些存储库中部署自己的工件,使得代码的共享既简单又独立于源(可能是一个优势)。

总结一下这个很长的回复:使用Ivy / Maven / Gradle而不是简单的Ant构建。 这些工具允许您定义依赖项,并完成下载这些依赖项的所有工作,并确保使用声明的版本。

在个人笔记上,当我发现这些工具的那一天,我对Java的依赖处理的看法从噩梦到天堂,因为我现在只需要说我使用这个工具的非常版本和maven(在我的情况下),完成下载并存储在我计算机上正确位置的所有后台工作。

源控制系统设计用于保存文本源代码。 它们可以保存二进制文件,但这并不是它们的设计目的。 在某些情况下,将二进制文件放在源代码管理中是有意义的,但通常可以通过不同的方式更好地管理Java依赖项。

理想的设置是允许您在源代码管理之外管理依赖关系的设置。 您应该能够在源之外管理您的依赖项,并简单地从源中“指向”所需的依赖项。 这有几个好处:

  • 您可以拥有多个依赖于相同二进制文件的项目,而无需保留每个二进制文件的单独副本。 中型项目通常有数百个依赖的二进制文件。 这可能导致大量重复,从而浪费本地和备份资源。
  • 可以在本地环境中或公司实体内集中管理二进制文件的版本。
  • 在许多情况下,源控制服务器不是本地资源。 添加一堆二进制文件会减慢速度,因为它会增加需要通过较慢连接发送的数据量。
  • 如果您正在创建战争,可能需要一些开发所需的jar,而不是部署,反之亦然。 一个好的依赖管理工具可以让您轻松高效地处理这些类型的问题。
  • 如果您依赖于另一个项目的二进制文件,它可能会经常更改。 这意味着您可以使用新版本不断覆盖二进制文件。 由于版本控制将保留每个副本,因此它可能会迅速增长到难以管理的大小 – 特别是如果您有任何类型的持续集成或自动构建脚本创建这些二进制文件。
  • 依赖关系管理系统为您依赖二进制文件提供了一定程度的灵活性。 例如,在本地计算机上,您可能希望依赖于文件系统上的最新版本的依赖项。 但是,在部署应用程序时,您希望将依赖项打包为jar并包含在文件中。

Maven的依赖管理function可以帮助您解决这些问题,并可以帮助您根据需要定位和检索二进制依赖项。 常春藤也是另一个工具,但是对于Ant来说。

它们是二进制文件:

  • 最好引用源代码,因为这就是你使用源代码控制的原因。
  • 系统无法告诉您文件之间的差异
  • 如果它们是从同一存储库中的源代码编译的,它们就会成为合并冲突的来源。
  • 某些系统(例如SVN)与大型二进制文件的处理效果不佳。

换句话说,更好地引用源代码,并调整构建脚本以使一切正常。

将jar文件提交到SCM的决定通常受所使用的构建工具的影响。 如果以传统方式使用Maven,那么你真的没有选择。 但是如果您的构建系统允许您选择,我认为将依赖项提交给SCM以及依赖于它们的源代码是个好主意。

这适用于与您的项目处于单独发布周期的第三方jar子和内部jar子。 例如,如果您有一个包含常用实用程序类的内部jar文件,我会在使用它的每个项目下将其提交给SCM。

如果使用CVS,请注意它不能有效地处理二进制文件。 SVN存储库不区分二进制文件和文本文件。

http://svnbook.red-bean.com/en/1.5/svn.forcvs.binary-and-trans.html

针对Mark发布的答案进行更新:

WRT要点1:我想说即使是一个大型项目也有不少普遍存在数百个依赖项。 在任何情况下,磁盘使用(通过在每个使用它的项目中保留依赖项的单独副本)不应该是您主要关注的问题。 与处理Maven存储库的复杂性所耗费的时间相比,磁盘空间便宜。 在任何情况下,本地Maven存储库将消耗比实际使用的依赖项更多的磁盘空间。

Bullet 3:Maven不会为您节省等待网络流量的时间。 反之亦然。 使用源代码管理中的依赖项,进行结帐,然后从一个分支切换到另一个分支。 你很少需要再次检查相同的jar子。 如果你这样做,只需几分钟。 Maven是一个慢速构建工具的主要原因是它即使在没有需要时也可以进行网络访问。

Bullet Point 4:你的观点并不是反对在SCM中存储jar的论据,只要你学会了Maven,Maven就很容易了,只有在出现问题时它才有效。 然后变得困难,你的效率提升很快就会消失。 在效率方面,当事情正常工作时,Maven有一个小的上升空间,而当事情没有时,Maven有一个很大的缺点。

Bullet Point 5:SVN等版本控制系统不会为每个文件的每个版本保留单独的副本。 它将它们有效地存储为增量。 您的SVN存储库不太可能增长到“无法管理”的大小。

Bullet Point 6:你的观点不是反对存储文件的论据是SCM。 您提到的用例可以通过自定义Ant构建轻松处理。