Understanding Gradle Dependencies Graph Symbols
The article explains Gradle's dependency‑graph symbols—arrow (→) for version conflicts, (c) for constraint‑driven versions, (*) for omitted subtrees, and markers for strict or forced versions—showing how to read the output, identify conflicts, and apply proper resolution strategies.
Gradle's dependencies command is frequently used to locate version‑related issues in third‑party libraries. This article analyses the special symbols that appear in the command output and explains how they affect dependency resolution.
The most common symbols are:
-> – indicates a version conflict where the selected version is upgraded to a higher one.
(c) – marks a dependency that comes from a constraints block.
(*) – denotes an omitted subtree that has already been displayed elsewhere.
Dependency resolution
The -> arrow shows that the original version (left side) was replaced by the version on the right because of a conflict. Gradle generally selects the highest version, though there are many edge cases.
// module A, tag 1.0.0, build.gradle
dependencies {
implementation 'com.netease.cloudmusic.android:module_c:1.0.0'
implementation 'com.netease.cloudmusic.android:module_d:1.0.0'
}
// app, build.gradle
dependencies {
implementation 'com.netease.cloudmusic.android:module_a:1.0.0'
}When a conflict occurs, the output may look like:
+--- com.netease.cloudmusic.android:module_a:1.0.0
| +--- com.netease.cloudmusic.android:module_c:1.0.0 -> 1.1.0
| \--- com.netease.cloudmusic.android:module_d:1.0.0
\--- com.netease.cloudmusic.android:module_b:1.0.0
\--- com.netease.cloudmusic.android:module_c:1.1.0Dependency omitted
The (*) symbol indicates that a subtree has been omitted because it was already printed earlier. This keeps the graph readable for large projects.
+--- com.netease.cloudmusic.android:module_a:1.0.0
| +--- com.netease.cloudmusic.android:module_c:1.0.0
| \--- com.netease.cloudmusic.android:module_d:1.0.0
+--- com.netease.cloudmusic.android:module_b:1.0.0
| \--- com.netease.cloudmusic.android:module_a:1.0.0 (*)
+--- com.netease.cloudmusic.android:module_e:1.0.0
| \--- com.netease.cloudmusic.android:module_a:1.0.0 (*)
\--- com.netease.cloudmusic.android:module_f:1.0.0
\--- com.netease.cloudmusic.android:module_a:1.0.0 (*)Dependency constraint
The (c) marker appears when a version is forced by a constraints block. This allows you to upgrade or align transitive dependencies without adding a direct dependency.
dependencies {
constraints {
implementation('com.netease.cloudmusic.android:module_c:1.1.0') {
because 'previous versions have a bug impacting this application'
}
}
}When the constraint is active, the output shows the (c) marker:
+--- com.netease.cloudmusic.android:module_a:1.0.0
| +--- com.netease.cloudmusic.android:module_c:1.0.0 -> 1.1.0
| \--- com.netease.cloudmusic.android:module_d:1.0.0
\--- com.netease.cloudmusic.android:module_c:1.1.0 (c)If the consuming module later upgrades, the constrained version may become redundant and disappear from the graph.
Downgrading versions
Gradle also supports explicit downgrades via strictly or force . The strictly keyword is displayed in the graph, while force is deprecated in newer Gradle versions.
// app, build.gradle
dependencies {
implementation 'com.netease.cloudmusic.android:module_a:1.1.0'
implementation('com.netease.cloudmusic.android:module_c') {
version { strictly '1.0.0' }
}
} +--- com.netease.cloudmusic.android:module_a:1.1.0
| +--- com.netease.cloudmusic.android:module_c:1.1.0 -> 1.0.0
| \--- com.netease.cloudmusic.android:module_d:1.1.0
\--- com.netease.cloudmusic.android:module_c:{strictly 1.0.0} -> 1.0.0Using force produces a similar result but without a visible marker:
// app, build.gradle
dependencies {
implementation 'com.netease.cloudmusic.android:module_a:1.1.0'
implementation('com.netease.cloudmusic.android:module_c:1.0.0') { force = true }
} +--- com.netease.cloudmusic.android:module_a:1.1.0
| +--- com.netease.cloudmusic.android:module_c:1.1.0 -> 1.0.0
| \--- com.netease.cloudmusic.android:module_d:1.1.0
\--- com.netease.cloudmusic.android:module_c:1.0.0Summary
By recognizing the symbols -> , (c) , (*) , and the keywords strictly and force , developers can more accurately interpret Gradle's dependency graph, locate version conflicts, and apply appropriate resolution strategies.
NetEase Cloud Music Tech Team
Official account of NetEase Cloud Music Tech Team
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.