Understand Composer Versions

🦖 This post was published in 2014 and is most likely outdated.

Here are some extracts from Composer’s documentation reorganized to better understand how package versions and stability work.

Versions of a package

Format (doc)

[Versions] follow the format of X.Y.Z or vX.Y.Z with an optional suffix of -dev, -patch, -alpha, -beta or -RC. The patch, alpha, beta and RC suffixes can also be followed by a number.



Versions from git tags (doc)

For every tag that looks like a version, a package version of that tag will be created. It should match X.Y.Z or vX.Y.Z, with an optional suffix of -patch, -alpha, -beta or -RC. The suffixes can also be followed by a number.

Here are a few examples of valid tag names:


Note: Even if your tag is prefixed with v, a version constraint in a require statement has to be specified without prefix (e.g. tag v1.0.0 will result in version 1.0.0).

Versions from git branches (doc)

For every branch, a package development version will be created. If the branch name looks like a version, the version will be {branchname}-dev. For example a branch 2.0 will get a version 2.0.x-dev (the .x is added for technical reasons, to make sure it is recognized as a branch, a 2.0.x branch would also be valid and be turned into 2.0.x-dev as well. If the branch does not look like a version, it will be dev-{branchname}. master results in a dev-master version.

Here are some examples of version branch names:

1.0 (equals 1.0.x)

Note: When you install a development version, it will be automatically pulled from its source. See the install command for more details.

Referencing to a version

An object which maps package names to version constraints. […]

require additionally support stability flags (root-only). These allow you to further restrict or expand the stability of a package beyond the scope of the minimum-stability setting. You can apply them to a constraint, or just apply them to an empty constraint if you want to allow unstable packages of a dependency for example.


 "require": {
     "monolog/monolog": "1.0.*@beta",    <-- @beta applied to a constraint
     "acme/foo": "@dev"                  <-- @dev applied to an empty constraint

If one of your dependencies has a dependency on an unstable package you need to explicitly require it as well, along with its sufficient stability flag.


 "require": {
     "doctrine/doctrine-fixtures-bundle": "dev-master",
     "doctrine/data-fixtures": "@dev"

Version constraints (doc)

Exact version 1.0.2 You can specify the exact version of a package.
Range >=1.0 >=1.0,<2.0 >=1.0,<1.1 | >=1.2 By using comparison operators you can specify ranges of valid versions. Valid operators are >, > =, <, <=, !=.You can define multiple ranges, separated by a comma, which will be treated as a logical AND. A pipe symbol | will be treated as a logical OR. AND has higher precedence than OR.
Wildcard 1.0.* You can specify a pattern with a * wildcard. 1.0.* is the equivalent of >=1.0,<1.1.
Tilde Operator ~1.2 Very useful for projects that follow semantic versioning. ~1.2 is equivalent to >=1.2,<2.0. For more details, read the next section below.

Next Significant Release (Tilde Operator) (doc)

The ~ operator is best explained by example: ~1.2 is equivalent to >=1.2,<2.0, while ~1.2.3 is equivalent to >=1.2.3,<1.3. As you can see it is mostly useful for projects respecting semantic versioning. A common usage would be to mark the minimum minor version you depend on, like ~1.2 (which allows anything up to, but not including, 2.0). Since in theory there should be no backwards compatibility breaks until 2.0, that works well. Another way of looking at it is that using ~ specifies a minimum version, but allows the last digit specified to go up.

Note: Though 2.0-beta.1 is strictly before 2.0, a version constraint like ~1.2 would not install it. As said above ~1.2 only means the .2 can change but the 1. part is fixed.


Default (doc)

By default only stable releases are taken into consideration. If you would like to also get RC, beta, alpha or dev versions of your dependencies you can do so using stability flags. To change that for all packages instead of doing per dependency you can also use the minimum-stability setting.

Minimum stability (doc)

This defines the default behavior for filtering packages by stability. This defaults to stable, so if you rely on a dev package, you should specify it in your file to avoid surprises.

All versions of each package are checked for stability, and those that are less stable than the minimum-stability setting will be ignored when resolving your project dependencies. Specific changes to the stability requirements of a given package can be done in require […].

Available options (in order of stability) are dev, alpha, beta, RC, and stable.


Install (doc)

The install command reads the composer.json file from the current directory, resolves the dependencies, and installs them into vendor.

If there is a composer.lock file in the current directory, it will use the exact versions from there instead of resolving them. This ensures that everyone using the library will get the same versions of the dependencies.

If there is no composer.lock file, composer will create one after dependency resolution.

Update (doc)

Will resolve all dependencies of the project and write the exact versions into composer.lock. […]

To update a few packages and not all:

composer update vendor/package vendor/package2

Show (doc)

To see all existing packages:

$ composer show

To see the details of one package:

composer show vendor/package

To see the details of a specific version of one package

composer show vendor/package 1.0.2

To see all installed package with versions:

$ composer show -i
alexandresalome/php-selenium     1.0.1      PHP Library for Selenium
behat/behat                      v2.5.0     Scenario-oriented BDD framework for ...
behat/common-contexts            v1.2.0     Commonly used contexts for Behat

To see what composer understood from the composer.json file:

$ composer show -s
php >=5.4.0
symfony/symfony 2.3.*
symfony/assetic-bundle 2.3.*
symfony/swiftmailer-bundle 2.3.*
symfony/monolog-bundle 2.3.*


See what composer understood from the composer.json file:

composer show -s | grep doctrine-migrations-bundle

See what version is installed:

composer show -i | grep doctrine-migrations-bundle

See if there exists some stable version for a package (here no):

$ composer show doctrine/doctrine-migrations-bundle
versions : * dev-master, 2.1.x-dev, 2.0.x-dev,
1.0.0-BETA4, 1.0.0-BETA3, 1.0.0-BETA2, v1.0.0-beta1