我对带有存储库的应用程序中使用的composer.lock
有点困惑。
我看到很多人说我们不应该从存储库中.gitignore
composer.lock
。
如果我在开发环境中更新我的库,我将有一个新的composer.lock
但我将无法将它们更新到生产中,对吗?
它不会在这个文件上产生冲突吗?
如果您更新库,则还需要提交锁定文件。它基本上声明您的项目已锁定到您正在使用的那些特定版本的库。
如果您提交更改,并且有人提取您的代码并更新依赖项,则锁文件应不被修改。如果它被修改,则意味着您拥有某些内容的新版本。
将其放在存储库中可确保您每个开发人员都使用相同的版本。
对于应用程序/项目:绝对是的。
作曲家文档对此进行了说明(强调):
将应用程序的 composer.lock(以及 composer.json)提交到版本控制中。
就像@meza说的:你应该提交锁定文件,这样你和你的合作者就在同一组版本上工作,并防止你说"但它在我的电脑上工作"。
对于库:可能不是。
作曲家文档对此事进行了说明:
注意:对于库,不一定建议提交锁定文件 (...
并在此处声明:
对于您的库,如果需要,您可以提交 composer.lock 文件。这可以帮助您的团队始终针对相同的依赖项版本进行测试。但是,此锁定文件不会对依赖于它的其他项目产生任何影响。它只对主项目有影响。
对于图书馆,我同意@Josh约翰逊的回答。
在为几个项目做了两种方式之后,我的立场是composer.lock
不应该作为项目的一部分提交。
composer.lock
是不是项目一部分的构建元数据。依赖项的状态应通过对依赖项进行版本控制(手动或作为自动生成过程的一部分),而不是由最后一个开发人员任意更新它们并提交锁定文件来控制。
如果您担心作曲家更新之间的依赖关系发生变化,那么您对版本控制方案缺乏信心。版本(1.0、1.1、1.2 等)应该是不可变的,您应该避免在初始功能开发之外使用"dev-"和"X.*"通配符。
提交锁定文件是依赖项管理系统的回归,因为依赖项版本现已恢复为隐式定义。
此外,您的项目永远不必在每个环境中重新生成或重新获取其依赖项,尤其是生产环境。您的可交付成果(tar,zip,phar,目录等)应该是不可变的,并且通过环境进行升级而无需更改。
- 不应直接在生产上更新依赖项。
- 您应该对composer.lock文件进行版本控制。
- 不应对实际依赖项进行版本控制。
1.不应直接更新对生产环境的依赖项,因为您不知道这将如何影响代码的稳定性。新依赖项可能会引入错误,它可能会改变影响您自己的代码行为方式,它可能与其他依赖项不兼容等。您应该在开发环境中执行此操作,然后进行适当的 QA 和回归测试等。
2. 您应该对composer.lock文件进行版本控制,因为这会存储有关依赖项以及依赖项的依赖项的信息,这些信息将允许您复制代码的当前状态。这很重要,因为您的所有测试和开发都是针对特定代码完成的。不关心您拥有的代码的实际版本类似于将代码更改上传到应用程序而不对其进行测试。如果要升级依赖项版本,这应该是一种自愿的行为,并且应采取必要的措施以确保一切正常。在恢复到以前的发布版本时损失一两个小时的正常运行时间可能会花费您很多钱。
您将看到的关于不需要composer.lock的论点之一是,您可以在composer.json文件中设置所需的确切版本,这样,每次有人运行composer install
时,它都会安装相同的代码。这是不正确的,因为您的依赖项有自己的依赖项,并且它们的配置可能以允许更新到 Subversion甚至整个版本的格式指定。
这意味着,即使你指定要在composer.json中使用 Laravel 4.1.31,Laravel 在其composer.json文件中也可能有自己的依赖项,作为 Symfony 事件调度程序:2.*。 使用这种配置,您最终可能会使用带有Symfony事件调度程序2.4.1的Laravel 4.1.31,而您团队中的其他人可以使用带有事件调度程序2.6.5的Laravel 4.1.31,这完全取决于您上次运行作曲家安装的时间。
因此,将composer.lock文件放在版本系统中将存储此子依赖项的确切版本,因此,当您和您的队友进行 composer 安装时(这是您将基于composer.lock安装依赖项的方式),你们都将获得相同的版本。
如果要更新怎么办?然后在您的开发环境中运行:composer update
,这将生成一个新的composer.lock文件(如果有新内容),并在您测试它之后,QA 测试和回归测试它和其他东西。您可以推送它供其他人下载新的composer.lock,因为它可以安全升级。
3. 您不应该对实际依赖项进行版本控制,因为这毫无意义。使用composer.lock,您可以安装依赖项的确切版本,而无需提交它们。为什么要将依赖项的 10000 个文件添加到存储库中,而不应该更新它们。如果您需要更改其中之一,则应将其分叉并在那里进行更改。如果您担心每次构建或发布时都必须获取实际的依赖项,Composer 有不同的方法来缓解此问题,缓存、zip 文件等。
将
composer.json
提交到项目中,团队中的其他所有人都可以运行 composer install 来安装项目依赖项。锁定文件的要点是记录安装的确切版本,以便可以重新安装它们。这意味着,如果您的版本规范为 1.*,并且您的同事运行安装 1.2.4 的作曲家更新,然后提交 composer.lock 文件,则当您安装作曲家时,即使您已发布 1.3.0,您也将获得 1.2.4。这可确保参与项目的每个人都具有相同的确切版本。
这意味着,如果自上次完成作曲家安装以来已提交任何内容,那么,如果没有锁定文件,您将获得新的第三方代码被拉下。
同样,如果您担心密码破译,这是一个问题。这也是为什么将Composer视为以composer.lock文件为中心的重要原因之一。
来源: 作曲家: 这都是关于锁定文件的。
将应用程序的 composer.lock(以及 composer.json)提交到版本控制中。这很重要,因为 install 命令会检查是否存在锁定文件,如果存在,它会下载其中指定的版本(无论 composer.json 说什么)。这意味着设置项目的任何人都可以下载完全相同的依赖项版本。您的 CI 服务器、生产计算机、团队中的其他开发人员、所有内容和每个人都在相同的依赖项上运行,这减轻了仅影响部署的某些部分的错误的可能性。即使您独自开发,在六个月内重新安装项目时,即使您的依赖项从那时起发布了许多新版本,您也可以确信安装的依赖项仍在工作。
来源:作曲家 - 基本用法。
如果您担心代码中断,则应将composer.lock
提交到版本控制系统,以确保所有项目协作者都使用相同的代码版本。如果没有锁定文件,您每次都会收到新的第三方代码被拉下。
例外情况是当您使用元应用程序时,应在安装时更新依赖项的库(如 Zend Framework 2 骨架应用程序)。因此,目标是在每次要开始开发时获取最新的依赖项。
来源: 作曲家: 一切都与锁定文件有关
另请参阅:作曲家更新和作曲家安装之间有什么区别?
显然是的。
这是因为本地安装的作曲家将优先选择composer.lock文件而不是composer.json。
如果锁定文件在 vcs 中不可用,作曲家将指向 composer.json 文件以安装最新的依赖项或版本。
文件composer.lock更深入地维护依赖关系,即它指向我们软件中包含的软件包版本的实际提交,因此这是最重要的文件之一,可以更精细地处理依赖关系。
这在踩踏中已经得到了充分的回答。
TL;博士
当然,你应该VCcomposer.lock
但我要说的是为什么
作曲家.json 角色
composer.json 是 PHP 包的依赖清单的入口点。
它一直在规定包开发人员遵循语义版本控制。
因此,通过这种方式,如果 x.y.z 中的 API 版本 (X) 已更改,您将了解有些事情您必须注意,或者您可以将您的版本锁定为某个"~x"
版本。
并非所有软件包都遵循 semversion
但是,有很多软件包没有遵循规则(5.3和5.4 api级别更改或损坏):
- 不遵守此语义原则(API 级别更改)
- 新软件包与最旧的API不兼容(未经良好测试和破坏)
解决方案编辑器.lock
作曲家想出了一个解决方案。 另一个用于锁定软件包版本的文件。(作曲家)
它包含确切的软件包版本,因此如果任何人想要拥有相同的依赖项版本,则可以从中受益。
在所有部署之间保持清单相同
值得一提的是,现代 Web 开发原则的 12 个因素之一是在所有部署中保持依赖项相同,因此每个部署都可以对其进行测试。 它们之间不会收缩。
为此:
您必须将 composer.lock 置于版本控制之下
在生产上只是:
composer install --no-dev
安装VC控制的锁定文件中的所有内容。 您之前已经完全测试过的部门。
composer.json & composer.lock 的最终用户
composer.json
是一个精简文件,供开发人员对 deps 和版本得出结论。
而composer.lock
旨在由部署(计算机)用于在部署上安装确切的版本号。
类比
它就像IP和域的类比:
IP(锁定文件)供机器使用
供人类使用的域 (JSON)
然而,人类(开发人员)和机器(部署)都可以阅读并从中受益,但每个版本都有一个更可取的版本。
这个问题没有确切的答案。
一般来说,作曲家不应该做构建系统应该做的事情,你不应该把 composer.lock 放在 VCS 中。作曲家可能会奇怪地把它倒过来。最终用户而不是生产用户不应使用锁定文件。通常,您的构建系统会保留快照、可重用目录等,而不是每次都保留空目录。人们从作曲家那里签出一个库,可能希望该库使用锁,以便对库加载的依赖项进行测试。
另一方面,这大大增加了版本管理的负担,您几乎肯定希望每个库有多个版本,因为依赖项将被严格锁定。如果每个库的版本可能略有不同,那么您需要一些多库版本支持,并且您还可以快速查看所需的依赖项的大小,因此建议将其保留在叶子上。
考虑到这一点,我真的不认为锁定文件对库或您自己的工作有用。它对我来说唯一的用途是在我的构建/测试平台中,该平台仅保留任何外部获取的资产,仅在请求时更新它们,为测试、构建和部署提供可重复的构建。虽然这可以保存在 VCS 中,但并不总是与源代码树一起保存,构建树要么在 VCS 结构中的其他地方,要么由其他地方的另一个系统管理。如果它存储在 VCS 中,是否将其保留在与源树相同的存储库中是值得商榷的,否则每次拉取都会带来大量构建资产。我非常喜欢将所有东西都放在一个安排良好的存储库中,除了生产/敏感凭据和膨胀。
SVN 可以比 git 做得更好,因为它不会强迫您获取整个存储库(尽管我怀疑 git 实际上也不是严格需要的,但对此的支持是有限的,而且它不常用)。简单的构建存储库通常只是将构建树合并/导出到的覆盖分支。有些人将外部资源组合在他们的源代码树中,或者进一步分离,外部,构建和源树。它通常有两个目的,构建缓存和可重复构建,但有时至少在某个级别上将其分开也允许新/空白构建和多个构建。
有许多策略可以做到这一点,除非您将外部源代码保留在源代码树中,否则它们都不能特别适用于持久化源列表。
他们还有文件中的哈希值之类的东西,当两个人更新包时如何合并?仅凭这一点就应该让你觉得这可能是误解。
人们为锁定文件提出的论点是他们对问题采取非常具体和限制性的观点的情况。想要可重复的构建和一致的构建?在 VCS 中包含供应商文件夹。然后,您还可以加快获取资产的速度,并且不必在构建过程中依赖可能损坏的外部资源。除非绝对必要,否则我创建的任何生成和部署管道都不需要外部访问。如果必须更新外部资源,则只需更新一次。作曲家试图实现的目标对于分布式系统是有意义的,除非如前所述,这是没有意义的,因为它最终会导致库更新的库依赖地狱,常见的冲突和更新的速度与更新包最慢一样慢。
此外,我猛烈地更新。每次开发时,我都会更新和测试所有内容。有一个非常非常小的窗口,可以潜入重要的版本漂移。实际上,当坚持语义版本控制时(这往往是针对作曲家的),你不应该有那么多兼容性问题或损坏。
在 composer.json 中,您可以放置所需的包及其版本。您可以在那里锁定版本。但是,这些包也依赖于不会被 composer.json 锁定的动态版本(尽管我不明白为什么如果您确实希望它们被版本锁定,为什么您不能自己将它们放在那里)所以运行作曲家安装的其他人在没有锁定的情况下会得到不同的东西。你可能不太关心这一点,或者你可能在乎,这取决于。你应该关心吗?可能至少有一点,足以确保您在任何情况下都了解它并产生潜在影响,但如果您总是有时间先进行 DRY 运行并修复任何更新的内容,那也可能不是问题。
作曲家试图避免的麻烦有时只是不存在,而作曲家锁定文件可能会带来的麻烦是巨大的。他们绝对没有权利告诉用户他们应该或不应该对构建资产和源资产做什么(是否加入 VCS 中的单独资产),因为这不关他们的事,他们不是你或我的老板。"作曲家说"不是权威,他们不是你的上级,也没有在这个问题上给任何人任何优势。只有你知道你的真实情况,以及什么是最好的。但是,他们可能会为不了解事物如何工作的用户建议默认操作方案,在这种情况下您可能希望遵循它,但我个人认为这不是了解事情如何工作并能够正确制定您的要求的真正替代品。最终,他们对这个问题的回答是最好的猜测。制作作曲家的人不知道你应该把你的作曲家锁在哪里,他们也不应该。他们唯一的责任就是告诉你它是什么以及它做了什么。除此之外,您需要决定什么最适合您。
保留锁定文件对于可用性来说是有问题的,因为作曲家对它是否使用锁或 JSON 非常保密,并且并不总是很好地同时使用两者。如果你运行安装,它只使用它出现的锁定文件,所以如果你向 composer.json 添加一些东西,那么它不会被安装,因为它不在你的锁中。操作真正做什么以及它们在 json/lock 文件方面正在做什么根本不直观,有时甚至似乎没有意义(帮助说安装需要一个包名称,但在尝试使用它时它说不)。
要更新锁或基本上应用来自 json 的更改,您必须使用 update,并且您可能不想更新所有内容。锁优先选择应安装的内容。如果有锁定文件,则使用该文件。您可以在一定程度上限制更新,但系统仍然一团糟。
更新需要一段时间,需要 RAM 的演出。我也怀疑,如果你拿起一个一段时间没有被触及的项目,它看起来是它拥有的版本,随着时间的推移会有更多的版本,它可能不会有效地做到这一点,这只会扼杀它。
当涉及到秘密复合命令时,他们非常非常狡猾,你不能指望是复合的。默认情况下,"作曲家删除"命令将显示为映射到作曲家更新和作曲家删除。
你真正需要问的问题不是你是否应该将锁保留在你的源代码树中,或者你是否应该以某种方式将它持久化,而是你应该问它实际上做了什么,然后你可以自己决定什么时候需要持久化它以及在哪里。
我会指出,当您拥有强大的外部依赖持久性策略时,拥有锁的能力是一种极大的便利,因为它会跟踪您对跟踪该(来源)和更新它有用的信息,但如果您不这样做,那么它既不在这里也不在那里。当它被迫进入你的喉咙作为强制选项让它污染你的源树时,它是没有用的。在遗留代码库中发现这是一件非常普遍的事情,人们对 composer.json 进行了大量更改,这些更改尚未真正应用,并且在人们尝试使用 composer 时被破坏。没有作曲家锁定,没有不同步问题。
对于 Heroku 上的任何人,答案都很清楚"是的,应该提交":
如果
composer.json
在其require
部分中指定任何类型的依赖项,则通过运行composer update
生成的相应composer.lock
也必须提交到存储库,否则推送将被拒绝。
来源:Heroku PHP支持:激活。