应该将composer.lock致力于版本控制吗?


529

我对composer.lock在带有存储库的应用程序中使用感到有些困惑。

我看到许多人说我们不应该.gitignore composer.lock从存储库中获取。

如果我在开发环境中更新库,我将拥有一个新库,composer.lock但无法将其更新到生产环境中,对吗?

它不会在该文件上产生冲突吗?


1
该链接现在已失效@markus
Kyrre

Answers:


672

如果更新库,则也要提交锁文件。它基本上表明您的项目已锁定到您正在使用的那些特定版本的库。

如果您提交更改,并且有人拉您的代码并更新了依赖性,则锁定文件应保持不变。如果它被修改,则意味着您具有某个内容的新版本。

在存储库中拥有它可以确保每个开发人员都使用相同的版本。


5
好的,但是想象一下,如果我从生产环境中更新库,composer.lock将被覆盖,因此下一个生产中的提取将要求我合并此文件...
Pierre de LESPINAY 2012年

7
如果composer.lock被修改,则需要将修改推回到存储库中。如果要将软件绑定到给定版本的库,请在配置中明确进行。这样,锁将永远不会改变。将锁定文件视为依赖关系管理问题的指示器,需要以一种或另一种方式解决该问题。
meza 2012年

360
在生产环境中,您不应该更新依赖项,而应该运行composer install该依赖项,该依赖项将从锁定文件中读取并且不更改任何内容。
Seldaek 2012年

112
“在生产中你不应该更新您的依赖关系”应写在全部大写
华金属罗伯斯

75
@JoaquínL.Robles在生产中,您不应该更新您的依赖!:)
ЕлинЙ.

201

对于应用程序/项目:绝对可以。

作曲家文档在此(重点)规定:

将应用程序的composer.lock(以及composer.json)提交到版本控制中。

就像@meza所说:您应该提交锁定文件,这样您和您的协作者才能使用同一组版本,并避免使用诸如“但是在我的计算机上有效”之类的说法。;-)

对于图书馆:可能不会。

作曲家文档中对此事项进行了说明:

注意:对于库,不一定建议提交锁定文件(...)

在这里声明

对于您的库,您可以根据需要提交composer.lock文件。这可以帮助您的团队始终针对相同的依赖项版本进行测试。但是,此锁定文件对依赖它的其他项目不会有任何影响。它仅对主项目有影响。

对于图书馆,我同意@Josh Johnson的回答。


为什么将工作中的项目与“图书馆”区别对待?
乔什·约翰逊

4
也许“同事”一词在这里令人困惑,我将其更改为合作者。主要区别在于“主项目”与库,其中主项目由一个或多个库和集成这些库的代码组成。从主项目运行composer时,它不使用库的composer.lock文件,因此它将以最新版本安装其依赖项。我认为测试您的库时应该类似。
Jeroen Fiege 2014年

2
使用库提交锁定文件可能是一件好事-锁定文件记录了运行测试套件时安装了哪些版本的依赖项。这对于团队而言尤其重要,在持续集成环境中尤其如此。
mindplay.dk

在主干2分支中重新集成时,这两个琐碎的冲突都会产生,这两个分支都通过composer安装了新软件包。现在发生了:)
g4b0

2
@tonix,我可以一定的权限回答这个问题!我没有为提交composer.lock的原因是,无论如何,我的CI每晚都会构建master。它保证,如果任何库的依赖项都存在升级问题,则库的用户将遇到该配置项失败。效果不错!
西奥多·R·史密斯,

86

在少数几个项目中完成这两种方式后,我的立场是composer.lock不应将其作为项目的一部分来落实。

composer.lock是构建元数据,它不是项目的一部分。依赖项的状态应该通过您对它们进行版本控制的方式来控制(手动或作为自动构建过程的一部分),而不是由最后的开发人员随意更新和提交锁定文件。

如果您担心在作曲家更新之间您的依赖关系会发生变化,那么您对版本控制方案将缺乏信心。版本(1.0、1.1、1.2等)应该是不变的,在初始功能开发之外,应避免使用“ dev-”和“ X. *”通配符。

提交锁定文件是您的依赖项管理系统的回归,因为依赖项版本现在已恢复为隐式定义。

同样,您的项目永远不必在每个环境(尤其是产品)中都进行重建或重新获得其依赖项。您的可交付成果(tar,zip,phar,目录等)应该是不变的,并且可以通过环境进行升级而无需更改。


19
同意 我觉得在composer.json更明确地说明所需版本的地方指定依赖版本更有意义。但是,如果您设置特定版本,则最好提交composer.lock。如果中指定的版本composer.json与根据所安装的版本不同,这会造成混淆composer.lock。此外,它取决于应用程序(内部发布或一般发布)及其开发周期。当然,作曲家文档的确以粗体显示“将应用程序的composer.lock(以及composer.json一起)提交到版本控制中”。明智地选择=)
Quinn Comendant 2014年

10
经过大量的探索之后,我决定在这一点上,作曲家文档是错误的:)我有一条规则,即我不向VCS添加生成的素材;我允许构建过程来处理。
乔什·约翰逊

10
使用您的生物机械按键创建的代码不是“生成的材料”吗?我不确定这是否是制定政策的可靠标准。=)
Quinn Comendant 2014年

5
@borfast我知道我来谈谈有点晚了,因此您到目前为止可能已经看到了这一点,但是您可以在中指定哈希值composer.json。在这一require部分中,您可以输入:"repo": "dev-master#2633721877cae79ad461f3ca06f3f77fb4fce02e"。这将1)转到分支,2)签出该哈希,3)如果在分支上未找到哈希,但是,它将签出指定分支的头(在这种情况下为master)。
CEPA

5
@CEPA-奇怪。我本来以为如果找不到哈希,它就会失败。似乎很危险。
弥敦道(Nathan JB)2015年

31
  1. 您不应该直接在Production上更新依赖项。
  2. 您应该版本控制您的composer.lock文件。
  3. 您不应该版本控制您的实际依赖关系。

1.您不应该直接在Production上更新依赖项,因为您不知道这将如何影响代码的稳定性。新的依赖项可能会引入一些错误,它可能会改变代码影响自己的行为方式,可能与其他依赖项不兼容,等等。您应该在开发环境中执行此操作,然后进行适当的QA和回归测试,等等。 。

2.您应该版本控制您的composer.lock文件,因为该文件存储有关您的依赖项以及您的依赖项的依赖项的信息,这些信息将允许您复制代码的当前状态。这很重要,因为所有测试和开发都是针对特定代码完成的。不在乎所拥有的代码的实际版本类似于将代码更改上传到应用程序而不进行测试。如果要升级依赖项版本,这应该是一个自愿的行为,并且应该采取必要的措施以确保一切仍然有效。失去一两个小时的正常运行时间来恢复到以前的版本可能会花费您很多钱。

关于不需要composer.lock的参数之一是,您可以在composer.json文件中设置所需的确切版本,这样,每次有人运行时composer install,它都将安装相同的版本。码。这是不正确的,因为您的依赖项具有它们自己的依赖项,并且它们的配置可能以允许更新子版本甚至整个版本的格式指定。

这意味着,即使您在composer.json中指定要使用Laravel 4.1.31 ,Laravel在composer.json文件中也可能具有其自己的依赖关系,即Symfony event-dispatcher:2. *。通过这种配置,您最终可能会获得带有Symfony事件调度程序2.4.1的Laravel 4.1.31,而您团队中的其他人可能会有带有事件调度程序2.6.5的Laravel 4.1.31,这都取决于何时是您最后一次运行composer安装。

因此,在版本系统中拥有composer.lock文件将存储此子依赖项的确切版本,因此,当您和您的队友进行composer安装时(这是您将基于composer安装依赖项的方式。锁定),您将获得相同的版本。

如果您想更新怎么办?然后在您的开发环境中运行:composer update,这将生成一个新的composer.lock文件(如果有新内容),并在对其进行测试,QA测试和回归测试之后对其进行填充。您可以将其推送给其他人,以下载新的composer.lock,因为它可以安全升级。

3.您不应该对实际的依赖项进行版本控制,因为这没有任何意义。使用composer.lock,您可以安装依赖项的确切版本,而无需提交它们。当不应该更新依赖时,为什么要将10000个依赖文件添加到仓库中。如果您需要更改其中之一,则应将其派生并在此处进行更改。而且,如果您担心每次构建或发行时都必须获取实际的依赖项,则作曲家可以采用不同的方法来缓解此问题,缓存,zip文件等。


1
谢谢,我想这个答案解释了为什么您应该版本composer.lock,如果不是,那么后果是什么,以及您是否可以忍受。
何塞·洛萨诺·埃尔南德斯

8

然后,您将提交composer.json到项目中,团队中的其他所有人都可以运行composer install来安装项目依赖项。

锁定文件的目的是记录已安装的确切版本,以便可以重新安装它们。这意味着,如果您的版本规格为1. *,并且您的同事运行composer update,该更新将安装1.2.4,然后提交composer.lock文件,则在您进行composer安装时,即使安装了1.2.4,如果1.3.0已发布。这样可以确保在项目上工作的每个人都具有相同的确切版本。

这意味着,如果自从上一次完成作曲家安装以来已提交了任何东西,那么在没有锁定文件的情况下,您将获得新的第三方代码

同样,如果您担心代码中断,这将是一个问题。这也是为什么将Composer放在composer.lock文件的中心很重要的原因之一。

资料来源:作曲家:全部与锁定文件有关


将应用程序的composer.lock(以及composer.json)提交到版本控制中。这很重要,因为install命令会检查是否存在锁定文件,如果存在,它将下载在那里指定的版本(无论composer.json说什么)。这意味着设置项目的任何人都将下载完全相同版本的依赖项。您的CI服务器,生产机器,团队中的其他开发人员,所有事物和每个人都在相同的依赖项上运行,从而减少了可能仅影响部署某些部分的错误。即使您是一个人开发,在重新安装项目的六个月中,即使自从那时以来您的依赖项发布了许多新版本,您也可以确信所安装的依赖项仍然有效。

资料来源:作曲家-基本用法


1

如果您担心代码被破坏,则应将其提交composer.lock给版本控制系统,以确保所有项目协作者都使用相同版本的代码。没有锁定文件,您每次都会获取新的第三方代码。

例外是当您使用元应用程序时,应在安装时更新依赖项的库(例如Zend Framework 2 Skeleton App)。因此,目标是每次您要开始开发时都获取最新的依赖项。

资料来源:作曲家:全部与锁定文件有关

另请参阅:composer更新和composer安装之间有什么区别?


1

对此没有确切答案。

一般来说,composer不应执行构建系统的预期工作,并且不应将composer.lock放入VCS。作曲家可能会奇怪地将其倒退。最终用户而不是生产者不应该使用锁定文件。通常,您的构建系统会保留快照,可重复使用的目录等,而不是每次都保留一个空目录。人们从作曲家签出一个库时,可能希望该库使用锁,以便针对库加载的依赖项进行测试。

另一方面,这极大地增加了版本管理的负担,几乎可以肯定每个库都需要多个版本,因为依赖关系将被严格锁定。如果每个库的版本可能都略有不同,则您需要一些库版本支持,并且还可以快速查看所需依赖项的大小,因此建议您将其保留在目录中。

考虑到这一点,我真的没有发现锁定文件对库或您自己的工作目录都没有用。它对我唯一的用途是在我的构建/测试平台中,该平台可持久存储任何从外部获取的资产,仅在需要时对其进行更新,从而提供可重复的构建以进行测试,构建和部署。尽管可以将其保留在VCS中,但并不总是与源树保持在一起,但是构建树将位于VCS结构中的其他位置,或由其他位置的其他系统管理。如果将其存储在VCS中,是否将其与源树保存在相同的存储库中是有争议的,因为否则每次拉动都会带来大量的构建资产。我非常喜欢将一切都安排在一个精心安排的仓库中,除了生产/敏感凭证和肿之外。

SVN可以比git做得更好,因为它不会强迫您获取整个仓库(尽管我怀疑git并不是严格要求的,但是对此的支持是有限的,并且不常用)。简单的构建存储库通常只是将构建树合并/导出到其中的覆盖分支。有些人将外部资源合并到其源代码树中,或者进一步分离外部,内部和源代码树。它通常用于两个目的,即构建缓存和可重复的构建,但是有时至少将其分开至少可以允许全新/空白构建和多个构建。

有很多策略可以用于此目的,除非您将外部源保留在源代码树中,否则这些策略都不能很好地与持久化源列表配合使用。

它们还具有文件的哈希值之类的东西,当两个人更新软件包时如何合并?仅此一项就应该让您认为这可能是错误的解释。

人们针对锁定文件提出的论点是他们对问题采取了非常具体和严格的看法的情况。是否需要可重复的构建和一致的构建?在VCS中包括供应商文件夹。然后,您还可以加快获取资源的速度,并且不必在构建过程中依赖于可能损坏的外部资源。除非绝对必要,否则我创建的构建和部署管道均不需要外部访问。如果必须更新外部资源,则只需一次。作曲家试图实现的目标对于分布式系统来说是有意义的,除非之前没有提到,否则它最终将导致库依赖地狱,导致库更新出现常见冲突,并且更新的速度与最慢的更新包一样慢。

另外,我猛烈地更新。每次开发时,我都会更新并测试所有内容。有一个很小的窗口可以潜入大量版本。实际上,同样,当维护语义版本控制时(通常是作曲家使用的),您并不会遇到太多的兼容性问题或破坏。

在composer.json中,放入所需的软件包及其版本。您可以在那里锁定版本。但是这些软件包还具有动态版本的依赖关系,这些动态版本不会被composer.json锁定(尽管我不明白为什么如果您希望将其锁定版本,为什么自己也不能将它们放在那里),所以其他人正在运行composer安装没有锁就得到一些不同的东西。您可能对此不太在意,或者您可能在乎,这取决于。你应该在乎吗?可能至少要足够一点,足以确保您在任何情况下都知道它,并可能产生影响,但是如果您始终有时间仅先运行DRY并修复已更新的任何内容,则可能不是问题。

麻烦的作曲家试图避免有时只是不存在,而拥有作曲家锁文件的麻烦很重要。他们绝对无权告诉用户他们应该做或不应该做的关于构建资产与源资产(无论是在VCS中加入独立资产)的事务,因为这与他们无关,他们不是您或我的老板。“作曲家说”不是权威,他们不是您的上司,也不给任何人在这个问题上的优势。只有您知道自己的真实情况,以及什么才是最好的。但是,对于不了解事物工作原理的用户,他们可能会建议采取默认的操作方案,在这种情况下,您可能希望遵循该操作,但我个人不认为那是 是了解事物如何工作并能够正确满足您的要求的真正替代。最终,他们对这个问题的答案是最好的猜测。作曲家的人不知道您应该将composer.lock放在哪里,他们也不应该。他们唯一的责任是告诉您它是什么以及它是做什么的。除此之外,您需要决定最适合您的。

保留锁文件对于可用性来说是个问题,因为作曲家对于使用锁还是使用JSON非常秘密,并且不能总是很好地结合使用两者。如果您运行install,它将仅使用锁定文件,因此会出现,因此,如果将内容添加到composer.json,则不会安装该文件,因为它不在您的锁定中。对于json / lock文件,实际上什么操作以及它们在做什么都是根本不直观的,有时甚至看起来没有任何意义(帮助说install需要一个软件包名称,但是在尝试使用它时,它说没有)。

要更新锁或基本上从json应用更改,您必须使用update,并且您可能不想更新所有内容。锁定优先于选择应安装的内容。如果有一个锁定文件,那就使用它。您可以限制更新,但是系统仍然很混乱。

更新需要一定的时间,还有大量的RAM。我还怀疑,如果您选择的项目从其所拥有的版本中看了一阵子没有被触及过,那么随着时间的流逝,将会出现更多的项目,并且它可能无法有效地完成工作,从而扼杀了它。

当涉及到您无法期望合成的秘密合成命令时,它们非常不知所措。默认情况下,例如,composer remove命令显示为映射到composer更新和composer remove。

您真正要问的问题不是您是否应该将锁保留在源树中,或者是否应该以某种方式将其保留在某处,而是应该询问其实际作用,然后您可以自己决定什么时候需要坚持以及何时坚持。

我将指出,拥有强大的外部依赖项持久化策略时,具有锁的功能非常方便,因为它可以跟踪您有用的信息,这些信息对于跟踪(起源)和更新它很有用,但是如果您不这样做的话那就既不是这里也不是那里 当它被迫下咽以使其污染源树时,这是没有用的。在遗留代码库中发现这是很平常的事情,在该代码库中,人们对composer.json进行了许多更改,这些更改尚未真正应用,并且在人们尝试使用composer时被破坏了。没有composer.lock,没有同步问题。


0

是的,很明显。

这是因为本地安装的作曲家将优先选择composer.lock文件,而不是composer.json。

如果vcs中没有锁文件,则编辑器将指向composer.json文件以安装最新的依赖项或版本。

文件composer.lock可以更深入地维护依赖关系,即它指向我们包含在软件中的软件包版本的实际提交,因此,这是更精细地处理依赖关系的最重要的文件之一。

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.