>=1.2.0 <2.0.0 matches every release from 1.2.0 up to, but not including, 2.0.0. A space between two comparators means AND, so a version has to pass both. Under npm’s default rules this range accepts exactly the versions ^1.2.0 does, and ^1.2.0 is the usual way to write it.
Against real versions
1.1.9 no below the floor
1.2.0 yes
1.5.3 yes
1.9.9 yes the highest match
1.6.0-beta.1 no a prerelease
2.0.0 no < leaves out the bound itself
2.0.0-rc.1 no a prerelease
Writing it
- No comma.
>=1.2.0, <2.0.0is how Cargo and Python write it. node-semver, npm’s range engine, rejects it withInvalid comparator: >=1.2.0,. <=keeps the bound.>=1.2.0 <=2.0.0also accepts 2.0.0 itself.||means OR.>=1.2.0 <2.0.0 || >=3.0.0accepts 1.2.0 and 3.1.0 but not 2.5.0.- Order doesn’t matter.
<2.0.0 >=1.2.0matches the same versions. - Leaving out the top is risky.
>=1.2.0alone accepts 2.0.0, 3.0.0 and every future major, breaking changes included.
Where it differs from ^1.2.0
node-semver compiles ^1.2.0 to >=1.2.0 <2.0.0-0, and 2.0.0-0 is the lowest possible prerelease of 2.0.0. The difference only shows when prereleases are let in with the includePrerelease option:
semver.satisfies('2.0.0-rc.1', '>=1.2.0 <2.0.0', { includePrerelease: true }) // true
semver.satisfies('2.0.0-rc.1', '^1.2.0', { includePrerelease: true }) // false
Without the option, which is how npm installs, neither range admits 2.0.0-rc.1 or 1.6.0-beta.1, because a prerelease only matches a range that names a prerelease of the same version. If you want the explicit form to keep 2.0.0’s prereleases out even with the option, write >=1.2.0 <2.0.0-0.
Other ecosystems
- Cargo:
>=1.2.0, <2.0.0, which is also what Cargo’s default requirement"1.2.0"means. - Composer: a space or a comma means AND, so
>=1.2.0 <2.0.0and>=1.2.0,<2.0.0both work. - Python (PEP 440):
>=1.2.0,<2.0.0, comma required.