Skip to content

VOL 00 / CH 05 / LESSON 03

5.3 Semantic Versioning, Ranges, and Conflicts ​

Prerequisites: Maven Basics

Estimated time: 15 minutes

You are ready to continue when: you can explain SemVer and avoid applying npm range syntax to other ecosystems

The manifest is ready, but ^1.2.3, ~=1.4.2, and [1.0,2.0) all look like ways to "allow a range." Pause there: version meaning and a package manager's range syntax belong to different layers and cannot be exchanged by appearance.

SemVer Description of Public API Changes ​

Assuming the publisher adheres to Semantic Versioning 2.0.0:

Version SegmentWhen to Increment
MAJORIncompatible changes in the public API
MINORAdding backward-compatible features, or marking public APIs as deprecated
PATCHFixing backward-compatible errors

0.y.z is used for initial development, and the public API should not be considered stable. Pre-release versions are lower than their corresponding stable versions; +build metadata does not participate in priority comparisons. The version number expresses the publisher's commitment, and it cannot substitute for change logs and testing.

npm's caret and tilde ​

json
{
  "dependencies": {
    "stable-api": "^1.2.3",
    "zero-minor-api": "^0.2.3",
    "patch-line": "~1.2.3"
  }
}
Syntaxnpm Range
^1.2.3>=1.2.3 <2.0.0
^0.2.3>=0.2.3 <0.3.0
^0.0.3>=0.0.3 <0.0.4
~1.2.3>=1.2.3 <1.3.0
1.2.3Exact match

The table describes ordinary releases. Prereleases have additional matching rules, so satisfying the numeric bounds does not automatically include them. The package names above are configuration examples, not installation targets; see node-semver prerelease rules.

Caret ranges are narrower in 0.x: ^0.2.3 allows versions below 0.3.0, while ^0.0.3 allows versions below 0.0.4. Check the leftmost non-zero component when determining the upper bound.

Python uses PEP 440 specifiers, such as >=1.2,<2 and ~=1.4.2; Maven ranges are written as [1.0,2.0). The three syntaxes cannot be interchanged.

Conflicts Are Not Always Solved by Installing Two Copies ​

  • Maven typically uses the nearest definition; when multiple artifacts are at the same depth, the one declared first takes precedence. dependencyManagement can manage versions, but it does not automatically introduce dependencies.
  • npm can retain multiple versions of a dependency at different points in the dependency tree, but peer dependencies can still cause conflicts.
  • pip typically installs only one version of a given distribution in a virtual environment. When constraints cannot be resolved, the installation should fail.
  • Gradle's choice is influenced by configuration, constraints, platform, rules, and lock settings.

Inspect the resolver's decision:

bash
npm explain PACKAGE_NAME
npm ls --all
./mvnw dependency:tree
./gradlew dependencyInsight --dependency NAME --configuration runtimeClasspath
python -m pip check

Before excluding transitive dependencies, confirm the final runtime classpath and compatibility requirements. Exclusion can inadvertently remove essential classes.

Before You Leave This Page ​

For ^0.2.3, identify the upper bound <0.3.0. When Maven paths request different versions, inspect depth, declaration order, and dependencyManagement. Then test the proposed upgrade: a lockfile records resolution, but cannot check application behavior.

→ Next: Comprehensive Experiment

Built with VitePress | Software Systems Atlas