# Smarter dependency downgrades

DevFeed: [Smarter dependency downgrades](<https://devfeed.tech/articles/smarter-dependency-downgrades-24703.md>)

Original publisher: [Read original article](<https://blog.gradle.org/version-downgrade>)

Author: Louis Jacomet

Published: 2020-03-12T04:00:00Z

Content type: article

Language: en

Sources: [The Gradle Blog](<https://devfeed.tech/sources/the-gradle-blog.md>)

Topics: [Gradle](<https://devfeed.tech/topics/gradle.md>), [Maven](<https://devfeed.tech/topics/maven.md>), [Library](<https://devfeed.tech/topics/library.md>), [Reverse Dependencies](<https://devfeed.tech/topics/reverse-dependencies.md>)

Tags: [build](<https://devfeed.tech/tags/build.md>), [compare](<https://devfeed.tech/tags/compare.md>), [dependencies](<https://devfeed.tech/tags/dependencies.md>), [dependency](<https://devfeed.tech/tags/dependency.md>), [gradle](<https://devfeed.tech/tags/gradle.md>), [graph](<https://devfeed.tech/tags/graph.md>), [libraries](<https://devfeed.tech/tags/libraries.md>), [upgrade](<https://devfeed.tech/tags/upgrade.md>)

## AI overview

This article explains how Gradle handles transitive dependency version conflicts and why semantic version downgrades matter. It introduces Gradle 6's strict version feature and compares Gradle's dependency resolution with Maven's order-dependent behavior, using Google Guava as an example.

## Source excerpt

One of the biggest challenges when dealing with transitive dependencies is to keep their versions under control. Popular libraries will show up as transitive dependencies in multiple places in your dependency graph. And it is quite likely that the version information will be different on each path. Through multiple blog posts, you have learned that Gradle offers a rich feature set for expressing complex dependency requirements. In this post, we will discuss why semantics matter when downgrading a dependency version. And you will learn about the strict version feature of Gradle 6 that provides this semantic information and effectively gives you a powerful and precise tool for dealing with this complex issue. In this post, we will use Google's Guava again as an illustrating example because: It is a very popular library, used by over 20,000 other libraries It has a complex history in terms of API stability which results in sometimes difficult upgrades in large dependency graphs In the dependency view below, taken from this build scan, we can see that many Guava versions are in play: The dependency declaration for this build is however quite simple: dependencies { implementation("org.optaplanner:optaplanner-core:7.24.0.Final") implementation("com.spotify:folsom:1.5.0") } With only two direct dependencies, we already have a conflict between four Guava versions. It will always resolve to 25.0-jre in this example. This is the result of Gradle accounting for all versions in a dependency graph and optimistically choosing the highest matching the constraints, 25.0-jre in our example. If we compare this Gradle project with a matching Maven project, we get a somewhat different result. With Maven, the first of the shortest path to a dependency will be used to determine the version. This means that, in our example, the Guava version is effectively order dependent since both libraries have a direct dependency on Guava. If com.spotify:folsom:1.5.0 is declared first in a Maven POM f