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