CINXE.COM
Package versioning | Dart
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="x-ua-compatible" content="ie=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><script>!function(e,t,a,n){e[n]=e[n]||[],e[n].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var g=t.getElementsByTagName(a)[0],m=t.createElement(a);m.async=!0,m.src="https://www.googletagmanager.com/gtm.js?id=GTM-5VSZM5J",g.parentNode.insertBefore(m,g)}(window,document,"script","dataLayer")</script><meta name="description" content="How Dart's package management tool, pub, handles versioning of packages."><title>Package versioning | Dart</title><link rel="icon" sizes="64x64" href="/assets/img/logo/dart-64.png" eleventy:ignore><link href="/assets/img/touch-icon-iphone.png" rel="apple-touch-icon" eleventy:ignore><link href="/assets/img/touch-icon-ipad.png" rel="apple-touch-icon" sizes="152x152" eleventy:ignore><link href="/assets/img/touch-icon-iphone-retina.png" rel="apple-touch-icon" sizes="180x180" eleventy:ignore><link href="/assets/img/touch-icon-ipad-retina.png" rel="apple-touch-icon" sizes="167x167" eleventy:ignore><meta name="twitter:card" content="summary"><meta name="twitter:site" content="@dart_lang"><meta name="twitter:title" content="Package versioning"><meta name="twitter:description" content="How Dart's package management tool, pub, handles versioning of packages."><meta property="og:title" content="Package versioning"><meta property="og:description" content="How Dart's package management tool, pub, handles versioning of packages."><meta property="og:url" content="/tools/pub/versioning/"><meta property="og:image" content="/assets/img/logo/dart-logo-for-shares.png?2" eleventy:ignore><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Display:wght@400&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Text:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0..1,0" rel="stylesheet"><link rel="stylesheet" href="/assets/css/main.css?v=2"><script src="/assets/js/os-tabs.js?v=2"></script><script src="/assets/js/main.js?v=2"></script><script>!function(e,a,t,n,c,o,s){e.GoogleAnalyticsObject=c,e[c]=e[c]||function(){(e[c].q=e[c].q||[]).push(arguments)},e[c].l=1*new Date,o=a.createElement(t),s=a.getElementsByTagName(t)[0],o.async=1,o.src="//www.google-analytics.com/analytics.js",s.parentNode.insertBefore(o,s)}(window,document,"script",0,"ga"),ga("create","UA-26406144-4","auto"),ga("send","pageview")</script></head><body class="default.html"><a id="skip-to-main" class="filled-button" href="#site-content-title" tabindex="1">Skip to main content</a><section id="cookie-notice"><div class="container"><p>dart.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.</p><div class="button-group"><a class="text-button" href="https://policies.google.com/technologies/cookies" target="_blank" rel="noopener">Learn more</a> <button id="cookie-consent" class="filled-button">OK, got it</button></div></div></section><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5VSZM5J" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript><div id="site-banner" role="alert"><p>Announcing Dart 3.7! Find out about updates to the language, analyzer, pub.dev, and more, in the <a href="https://medium.com/dartlang/announcing-dart-3-7-bf864a1b195c" target="_blank">blog post</a>.</p></div><header id="page-header" class="site-header"><nav id="mainnav" class="site-header"><div id="menu-toggle"><span class="material-symbols" title="Toggle side navigation menu." aria-label="Toggle side navigation menu." type="button">menu</span></div><a href="/" class="brand" title="Dart"><img src="/assets/img/logo/logo-white-text.svg" alt="Dart"></a><ul class="navbar"><li><a href="/overview" class="nav-link">Overview</a></li><li class="mainnav__get-started"><a href="/docs" class="nav-link active"><span>Docs</span></a></li><li><a href="/community" class="nav-link">Community</a></li><li><a href="/#try-dart" class="nav-link">Try Dart</a></li><li><a href="/get-dart" class="nav-link">Get Dart</a></li><li class="searchfield"><form action="/search" class="site-header__search form-inline" id="cse-search-box"><input type="hidden" name="cx" value="011220921317074318178:_yy-tmb5t_i"> <input type="hidden" name="ie" value="UTF-8"> <input type="hidden" name="hl" value="en"> <input class="site-header__searchfield form-control search-field" type="search" name="q" id="search-main" autocomplete="off" placeholder="Search" aria-label="Search"></form></li></ul></nav></header><div id="site-below-header"><div id="site-main-row"><div id="sidenav"><form action="/search/" class="site-header__search form-inline"><input class="site-header__searchfield form-control search-field" type="search" name="q" id="search-side" autocomplete="off" placeholder="Search" aria-label="Search"></form><ul class="navbar-nav"><li aria-hidden="true"><div class="sidenav-divider"></div></li><li class="nav-item"><a href="/overview" class="nav-link">Overview</a></li><li class="nav-item"><a href="/community" class="nav-link">Community</a></li><li class="nav-item"><a href="https://dartpad.dev" class="nav-link">Try Dart</a></li><li class="nav-item"><a href="/get-dart" class="nav-link">Get Dart</a></li><li class="nav-item"><a href="/docs" class="nav-link">Docs</a></li><li aria-hidden="true"><div class="sidenav-divider"></div></li></ul><ul class="nav"><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#-sidenav-1" role="button" aria-expanded="false" aria-controls="-sidenav-1"><span>Language</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1"><li class="nav-item"><a class="nav-link" href="/language"><div><span>Introduction</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-1-2" role="button" aria-expanded="false" aria-controls="-sidenav-1-2"><span>Syntax basics</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1-2"><li class="nav-item"><a class="nav-link" href="/language/variables"><div><span>Variables</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/operators"><div><span>Operators</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/comments"><div><span>Comments</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/metadata"><div><span>Metadata</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/libraries"><div><span>Libraries & imports</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/keywords"><div><span>Keywords</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-1-3" role="button" aria-expanded="false" aria-controls="-sidenav-1-3"><span>Types</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1-3"><li class="nav-item"><a class="nav-link" href="/language/built-in-types"><div><span>Built-in types</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/records"><div><span>Records</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/collections"><div><span>Collections</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/generics"><div><span>Generics</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/typedefs"><div><span>Typedefs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/type-system"><div><span>Type system</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-1-4" role="button" aria-expanded="false" aria-controls="-sidenav-1-4"><span>Patterns</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1-4"><li class="nav-item"><a class="nav-link" href="/language/patterns"><div><span>Overview & usage</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/pattern-types"><div><span>Pattern types</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/dart-patterns-records" target="_blank" rel="noopener"><div><span>Applied tutorial</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/language/functions"><div><span>Functions</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-1-6" role="button" aria-expanded="false" aria-controls="-sidenav-1-6"><span>Control flow</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1-6"><li class="nav-item"><a class="nav-link" href="/language/loops"><div><span>Loops</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/branches"><div><span>Branches</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/error-handling"><div><span>Error handling</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-1-7" role="button" aria-expanded="false" aria-controls="-sidenav-1-7"><span>Classes & objects</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1-7"><li class="nav-item"><a class="nav-link" href="/language/classes"><div><span>Classes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/constructors"><div><span>Constructors</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/methods"><div><span>Methods</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/extend"><div><span>Extend a class</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/mixins"><div><span>Mixins</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/enums"><div><span>Enums</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/extension-methods"><div><span>Extension methods</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/extension-types"><div><span>Extension types</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/callable-objects"><div><span>Callable objects</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-1-8" role="button" aria-expanded="false" aria-controls="-sidenav-1-8"><span>Class modifiers</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1-8"><li class="nav-item"><a class="nav-link" href="/language/class-modifiers"><div><span>Overview & usage</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/class-modifiers-for-apis"><div><span>Class modifiers for API maintainers</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/modifier-reference"><div><span>Reference</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-1-9" role="button" aria-expanded="false" aria-controls="-sidenav-1-9"><span>Concurrency</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1-9"><li class="nav-item"><a class="nav-link" href="/language/concurrency"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/async"><div><span>Asynchronous support</span></div></a></li><li class="nav-item"><a class="nav-link" href="/language/isolates"><div><span>Isolates</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-1-10" role="button" aria-expanded="false" aria-controls="-sidenav-1-10"><span>Null safety</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-1-10"><li class="nav-item"><a class="nav-link" href="/null-safety"><div><span>Sound null safety</span></div></a></li><li class="nav-item"><a class="nav-link" href="/null-safety/migration-guide"><div><span>Migrating to null safety</span></div></a></li><li class="nav-item"><a class="nav-link" href="/null-safety/understanding-null-safety"><div><span>Understanding null safety</span></div></a></li><li class="nav-item"><a class="nav-link" href="/null-safety/unsound-null-safety"><div><span>Unsound null safety</span></div></a></li><li class="nav-item"><a class="nav-link" href="/null-safety/faq"><div><span>FAQ</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#-sidenav-2" role="button" aria-expanded="false" aria-controls="-sidenav-2"><span>Core libraries</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-2"><li class="nav-item"><a class="nav-link" href="/libraries"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-core"><div><span>dart:core</span></div></a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-async"><div><span>dart:async</span></div></a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-math"><div><span>dart:math</span></div></a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-convert"><div><span>dart:convert</span></div></a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-io"><div><span>dart:io</span></div></a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop"><div><span>dart:js_interop</span></div></a></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/libraries/collections/iterables"><div><span>Iterable collections</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-2-10" role="button" aria-expanded="false" aria-controls="-sidenav-2-10"><span>Asynchronous programming</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-2-10"><li class="nav-item"><a class="nav-link" href="/libraries/async/async-await"><div><span>Tutorial</span></div></a></li><li class="nav-item"><a class="nav-link" href="/libraries/async/futures-error-handling"><div><span>Futures and error handling</span></div></a></li><li class="nav-item"><a class="nav-link" href="/libraries/async/using-streams"><div><span>Using streams</span></div></a></li><li class="nav-item"><a class="nav-link" href="/libraries/async/creating-streams"><div><span>Creating streams</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#-sidenav-3" role="button" aria-expanded="false" aria-controls="-sidenav-3"><span>Effective Dart</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-3"><li class="nav-item"><a class="nav-link" href="/effective-dart"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/effective-dart/style"><div><span>Style</span></div></a></li><li class="nav-item"><a class="nav-link" href="/effective-dart/documentation"><div><span>Documentation</span></div></a></li><li class="nav-item"><a class="nav-link" href="/effective-dart/usage"><div><span>Usage</span></div></a></li><li class="nav-item"><a class="nav-link" href="/effective-dart/design"><div><span>Design</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link active collapsible" data-toggle="collapse" data-target="#-sidenav-4" role="button" aria-expanded="true" aria-controls="-sidenav-4"><span>Packages</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="-sidenav-4"><li class="nav-item"><a class="nav-link" href="/tools/pub/packages"><div><span>How to use packages</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/useful-packages"><div><span>Commonly used packages</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/create-packages"><div><span>Creating packages</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/publishing"><div><span>Publishing packages</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/writing-package-pages"><div><span>Writing package pages</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/workspaces"><div><span>Workspaces (monorepo support)</span></div></a></li><li class="nav-item"><button class="nav-link active collapsible" data-toggle="collapse" data-target="#-sidenav-4-7" role="button" aria-expanded="true" aria-controls="-sidenav-4-7"><span>Package reference</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="-sidenav-4-7"><li class="nav-item"><a class="nav-link" href="/tools/pub/dependencies"><div><span>Dependencies</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/glossary"><div><span>Glossary</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/package-layout"><div><span>Package layout conventions</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/environment-variables"><div><span>Pub environment variables</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/pubspec"><div><span>Pubspec file</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/troubleshoot"><div><span>Troubleshooting pub</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/verified-publishers"><div><span>Verified publishers</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/security-advisories"><div><span>Security advisories</span></div></a></li><li class="nav-item"><a class="nav-link active" href="/tools/pub/versioning"><div><span>Versioning</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/custom-package-repositories"><div><span>Custom package repositories</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/tools/pub/private-files"><div><span>What not to commit</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#-sidenav-5" role="button" aria-expanded="false" aria-controls="-sidenav-5"><span>Development</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-5"><li class="nav-item"><a class="nav-link" href="/libraries/serialization/json"><div><span>JSON serialization</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/language/number-representation"><div><span>Number representation</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/google-apis"><div><span>Google APIs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/multiplatform-apps"><div><span>Multi-platform apps</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-5-5" role="button" aria-expanded="false" aria-controls="-sidenav-5-5"><span>Command-line & server apps</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-5-5"><li class="nav-item"><a class="nav-link" href="/server"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tutorials/server/get-started"><div><span>Get started</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tutorials/server/cmdline"><div><span>Write command-line apps</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tutorials/server/fetch-data"><div><span>Fetch data from the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tutorials/server/httpserver"><div><span>Write HTTP servers</span></div></a></li><li class="nav-item"><a class="nav-link" href="/server/libraries"><div><span>Libraries & packages</span></div></a></li><li class="nav-item"><a class="nav-link" href="/server/google-cloud"><div><span>Google Cloud</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-5-6" role="button" aria-expanded="false" aria-controls="-sidenav-5-6"><span>Web apps</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-5-6"><li class="nav-item"><a class="nav-link" href="/web"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/web/get-started"><div><span>Get started</span></div></a></li><li class="nav-item"><a class="nav-link" href="/web/deployment"><div><span>Deployment</span></div></a></li><li class="nav-item"><a class="nav-link" href="/web/libraries"><div><span>Libraries & packages</span></div></a></li><li class="nav-item"><a class="nav-link" href="/web/wasm"><div><span>Wasm compilation</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/libraries/core/environment-declarations"><div><span>Environment declarations</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#-sidenav-6" role="button" aria-expanded="false" aria-controls="-sidenav-6"><span>Interoperability</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-6"><li class="nav-item"><a class="nav-link" href="/interop/c-interop"><div><span>C interop</span></div></a></li><li class="nav-item"><a class="nav-link" href="/interop/objective-c-interop"><div><span>Objective-C & Swift interop</span></div></a></li><li class="nav-item"><a class="nav-link" href="/interop/java-interop"><div><span>Java & Kotlin interop</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-6-4" role="button" aria-expanded="false" aria-controls="-sidenav-6-4"><span>JavaScript interop</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-6-4"><li class="nav-item"><a class="nav-link" href="/interop/js-interop"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop/usage"><div><span>Usage</span></div></a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop/js-types"><div><span>JS types</span></div></a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop/tutorials"><div><span>Tutorials</span></div></a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop/past-js-interop"><div><span>Past JS interop</span></div></a></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/interop/js-interop/package-web"><div><span>Web interop</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#-sidenav-7" role="button" aria-expanded="false" aria-controls="-sidenav-7"><span>Tools & techniques</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-7"><li class="nav-item"><a class="nav-link" href="/tools"><div><span>Overview</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-7-2" role="button" aria-expanded="false" aria-controls="-sidenav-7-2"><span>Editors & debuggers</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-7-2"><li class="nav-item"><a class="nav-link" href="/tools/jetbrains-plugin"><div><span>IntelliJ & Android Studio</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/vs-code"><div><span>VS Code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-devtools"><div><span>Dart DevTools</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-7-2-4" role="button" aria-expanded="false" aria-controls="-sidenav-7-2-4"><span>DartPad</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-7-2-4"><li class="nav-item"><a class="nav-link" href="/tools/dartpad"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dartpad/troubleshoot"><div><span>Troubleshooting DartPad</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-7-3" role="button" aria-expanded="false" aria-controls="-sidenav-7-3"><span>Command-line tools</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-7-3"><li class="nav-item"><button class="nav-link collapsible" data-toggle="collapse" data-target="#-sidenav-7-3-1" role="button" aria-expanded="true" aria-controls="-sidenav-7-3-1"><span>Dart SDK</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="-sidenav-7-3-1"><li class="nav-item"><a class="nav-link" href="/tools/sdk"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-tool"><div><span>dart</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-analyze"><div><span>dart analyze</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-compile"><div><span>dart compile</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-create"><div><span>dart create</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-doc"><div><span>dart doc</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-fix"><div><span>dart fix</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-format"><div><span>dart format</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-info"><div><span>dart info</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/cmd"><div><span>dart pub</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-run"><div><span>dart run</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-test"><div><span>dart test</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/dartaotruntime"><div><span>dartaotruntime</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/experiment-flags"><div><span>Experiment flags</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible" data-toggle="collapse" data-target="#-sidenav-7-3-2" role="button" aria-expanded="true" aria-controls="-sidenav-7-3-2"><span>Other command-line tools</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="-sidenav-7-3-2"><li class="nav-item"><a class="nav-link" href="/tools/build_runner"><div><span>build_runner</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/webdev"><div><span>webdev</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-7-4" role="button" aria-expanded="false" aria-controls="-sidenav-7-4"><span>Static analysis</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-7-4"><li class="nav-item"><a class="nav-link" href="/tools/analysis"><div><span>Customizing static analysis</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deprecated/sound-problems"><div><span>Fixing common type problems</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/non-promotion-reasons"><div><span>Fixing type promotion failures</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/linter-rules"><div><span>Linter rules</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/diagnostic-messages"><div><span>Diagnostic messages</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-7-5" role="button" aria-expanded="false" aria-controls="-sidenav-7-5"><span>Testing & optimization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-7-5"><li class="nav-item"><a class="nav-link" href="/tools/testing"><div><span>Testing</span></div></a></li><li class="nav-item"><a class="nav-link" href="/web/debugging"><div><span>Debugging web apps</span></div></a></li></ul></li></ul></li><li aria-hidden="true"><div class="sidenav-divider"></div></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#-sidenav-9" role="button" aria-expanded="false" aria-controls="-sidenav-9"><span>Resources</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-9"><li class="nav-item"><a class="nav-link" href="/resources/dart-cheatsheet"><div><span>Language cheatsheet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/breaking-changes"><div><span>Breaking changes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/language/evolution"><div><span>Language evolution</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/language/spec"><div><span>Language specification</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/dart-3-migration"><div><span>Dart 3 migration guide</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#-sidenav-9-6" role="button" aria-expanded="false" aria-controls="-sidenav-9-6"><span>Coming from ...</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="-sidenav-9-6"><li class="nav-item"><a class="nav-link" href="/resources/coming-from/js-to-dart"><div><span>JavaScript to Dart</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/coming-from/swift-to-dart"><div><span>Swift to Dart</span></div></a></li></ul></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/resources/faq"><div><span>FAQ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/glossary"><div><span>Glossary</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/books"><div><span>Books</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/videos"><div><span>Videos</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tutorials"><div><span>Tutorials</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible" data-toggle="collapse" data-target="#-sidenav-10" role="button" aria-expanded="true" aria-controls="-sidenav-10"><span>Related sites</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="-sidenav-10"><li class="nav-item"><a class="nav-link" href="https://api.dart.dev" target="_blank" rel="noopener"><div><span>API reference</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://medium.com/dartlang" target="_blank" rel="noopener"><div><span>Blog</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://dartpad.dev" target="_blank" rel="noopener"><div><span>DartPad (online editor)</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://flutter.dev" target="_blank" rel="noopener"><div><span>Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev" target="_blank" rel="noopener"><div><span>Package site</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li></ul></div><main id="page-content"><div id="site-toc--side" class="site-toc"><header class="site-toc__title">Contents</header><ul class="section-nav"><li class="toc-entry nav-item"><a class="nav-link" href="#a-name-and-a-number">A name and a number</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#resolving-shared-dependencies">Resolving shared dependencies</a><ul class="nav"><li class="toc-entry nav-item"><a class="nav-link" href="#unshared-libraries-the-npm-approach">Unshared libraries (the npm approach)</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#version-lock-the-dead-end-approach">Version lock (the dead end approach)</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#version-constraints-the-dart-approach">Version constraints (the Dart approach)</a></li></ul></li><li class="toc-entry nav-item"><a class="nav-link" href="#semantic-versions">Semantic versions</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#constraint-solving">Constraint solving</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#constraint-context">Constraint context</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#constraint-solving-for-exported-dependencies">Constraint solving for exported dependencies</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#lockfiles">Lockfiles</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#when-things-go-wrong">When things go wrong</a><ul class="nav"><li class="toc-entry nav-item"><a class="nav-link" href="#you-can-have-disjoint-constraints">You can have disjoint constraints</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#you-can-have-ranges-that-dont-contain-a-released-version">You can have ranges that don't contain a released version</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#you-can-have-an-unstable-graph">You can have an unstable graph</a></li></ul></li><li class="toc-entry nav-item"><a class="nav-link" href="#summary">Summary</a></li></ul></div><article><div class="content"><div id="site-content-title"><h1>Package versioning</h1></div><div id="site-toc--inline" class="site-toc toc-collapsible toc-collapsed"><header class="site-toc__title">Contents <span class="site-toc--inline__toggle toc-toggle-down"><i class="material-symbols">keyboard_arrow_down</i></span> <span class="site-toc--inline__toggle toc-toggle-up"><i class="material-symbols">keyboard_arrow_up</i></span></header><ul class="section-nav"><li class="toc-entry"><a href="#a-name-and-a-number">A name and a number</a></li><li class="toc-entry"><a href="#resolving-shared-dependencies">Resolving shared dependencies</a><ul><li class="toc-entry"><a href="#unshared-libraries-the-npm-approach">Unshared libraries (the npm approach)</a></li><li class="toc-entry"><a href="#version-lock-the-dead-end-approach">Version lock (the dead end approach)</a></li><li class="toc-entry"><a href="#version-constraints-the-dart-approach">Version constraints (the Dart approach)</a></li></ul></li><li class="toc-entry"><a href="#semantic-versions">Semantic versions</a></li><li class="toc-entry"><a href="#constraint-solving">Constraint solving</a></li><li class="toc-entry"><a href="#constraint-context">Constraint context</a></li><li class="toc-entry"><a href="#constraint-solving-for-exported-dependencies">Constraint solving for exported dependencies</a></li><li class="toc-entry"><a href="#lockfiles">Lockfiles</a></li><li class="toc-entry"><a href="#when-things-go-wrong">When things go wrong</a><ul><li class="toc-entry"><a href="#you-can-have-disjoint-constraints">You can have disjoint constraints</a></li><li class="toc-entry"><a href="#you-can-have-ranges-that-dont-contain-a-released-version">You can have ranges that don't contain a released version</a></li><li class="toc-entry"><a href="#you-can-have-an-unstable-graph">You can have an unstable graph</a></li></ul></li><li class="toc-entry"><a href="#summary">Summary</a></li></ul><span class="site-toc--inline__toggle toc-toggle-more-items"><i class="material-symbols">more_horiz</i></span></div><p>The <a href="/tools/pub/packages">pub package manager</a> helps you work with versioning. This guide explains a bit about the history of versioning and pub's approach to it.</p><p>Consider this to be advanced information. To learn <em>why</em> pub was designed the way it was, keep reading. If you want to <em>use</em> pub, consult the <a href="/tools/pub/packages">other docs</a>.</p><p>Modern software development, especially web development, leans heavily on reusing lots and lots of existing code. That includes code <em>you</em> wrote in the past, but also code from third-parties, everything from big frameworks to small utility libraries. It's not uncommon for an application to depend on dozens of different packages and libraries.</p><p>It's hard to understate how powerful this is. When you see stories of small web startups building a site in a few weeks that gets millions of users, the only reason they can achieve this is because the open source community has laid a feast of software at their feet.</p><p>But this doesn't come for free: There's a challenge to code reuse, especially reusing code you don't maintain. When your app uses code being developed by other people, what happens when they change it? They don't want to break your app, and you certainly don't either. We solve this problem by <em>versioning</em>.</p><div class="header-wrapper"><h2 id="a-name-and-a-number">A name and a number</h2><a class="heading-link" href="#a-name-and-a-number" aria-label="Link to 'A name and a number' section">#</a></div><p>When you depend on some piece of outside code, you don't just say "My app uses <code>widgets</code>." You say, "My app uses <code>widgets 2.0.5</code>." That combination of name and version number uniquely identifies an <em>immutable</em> chunk of code. The people updating <code>widgets</code> can make all of the changes they want, but they promise to not touch any already released versions. They can put out <code>2.0.6</code> or <code>3.0.0</code> and it won't affect you one bit because the version you use is unchanged.</p><p>When you <em>do</em> want to get those changes, you can always point your app to a newer version of <code>widgets</code> and you don't have to coordinate with those developers to do it. However, that doesn't entirely solve the problem.</p><p>The version numbers discussed in this guide might differ from the version number set in the package filename. They might include <code>-0</code> or <code>-beta</code>. These notations don't affect dependency resolution.</p><div class="header-wrapper"><h2 id="resolving-shared-dependencies">Resolving shared dependencies</h2><a class="heading-link" href="#resolving-shared-dependencies" aria-label="Link to 'Resolving shared dependencies' section">#</a></div><p>Depending on specific versions works fine when your dependency <em>graph</em> is really just a dependency <em>tree</em>. If your app depends on a bunch of packages, and those things in turn have their own dependencies and so on, that all works fine as long as none of those dependencies <em>overlap</em>.</p><p>Consider the following example:</p><img src="/assets/img/tools/pub/PubConstraintsDiagram.png" alt="dependency graph"><p>So your app uses <code>widgets</code> and <code>templates</code>, and <em>both</em> of those use <code>collection</code>. This is called a <strong>shared dependency</strong>. Now what happens when <code>widgets</code> wants to use <code>collection 2.3.5</code> and <code>templates</code> wants <code>collection 2.3.7</code>? What if they don't agree on a version?</p><div class="header-wrapper"><h3 id="unshared-libraries-the-npm-approach">Unshared libraries (the npm approach)</h3><a class="heading-link" href="#unshared-libraries-the-npm-approach" aria-label="Link to 'Unshared libraries (the npm approach)' section">#</a></div><p>One option is to just let the app use both versions of <code>collection</code>. It will have two copies of the library at different versions and <code>widgets</code> and <code>templates</code> will each get the one they want.</p><p>This is what <a href="https://npmjs.org/">npm</a> does for node.js. Would it work for Dart? Consider this scenario:</p><ol><li><code>collection</code> defines some <code>Dictionary</code> class.</li><li><code>widgets</code> gets an instance of it from its copy of <code>collection</code> (<code>2.3.5</code>). It then passes it up to <code>my_app</code>.</li><li><code>my_app</code> sends the dictionary over to <code>templates</code>.</li><li>That in turn sends it down to <em>its</em> version of <code>collection</code> (<code>2.3.7</code>).</li><li>The method that takes it has a <code>Dictionary</code> type annotation for that object.</li></ol><p>As far as Dart is concerned, <code>collection 2.3.5</code> and <code>collection 2.3.7</code> are entirely unrelated libraries. If you take an instance of class <code>Dictionary</code> from one and pass it to a method in the other, that's a completely different <code>Dictionary</code> type. That means it will fail to match a <code>Dictionary</code> type annotation in the receiving library. Oops.</p><p>Because of this (and because of the headaches of trying to debug an app that has multiple versions of things with the same name), we've decided npm's model isn't a good fit.</p><div class="header-wrapper"><h3 id="version-lock-the-dead-end-approach">Version lock (the dead end approach)</h3><a class="heading-link" href="#version-lock-the-dead-end-approach" aria-label="Link to 'Version lock (the dead end approach)' section">#</a></div><p>Instead, when you depend on a package, your app only uses a single copy of that package. When you have a shared dependency, everything that depends on it has to agree on which version to use. If they don't, you get an error.</p><p>That doesn't actually solve your problem though. When you <em>do</em> get that error, you need to be able to resolve it. So let's say you've gotten yourself into that situation in the previous example. You want to use <code>widgets</code> and <code>templates</code>, but they are using different versions of <code>collection</code>. What do you do?</p><p>The answer is to try to upgrade one of those. <code>templates</code> wants <code>collection 2.3.7</code>. Is there a later version of <code>widgets</code> that you can upgrade to that works with that version?</p><p>In many cases, the answer will be "no". Look at it from the perspective of the people developing <code>widgets</code>. They want to put out a new version with new changes to <em>their</em> code, and they want as many people to be able to upgrade to it as possible. If they stick to their <em>current</em> version of <code>collection</code> then anyone who is using the current version <code>widgets</code> will be able to drop in this new one too.</p><p>If they were to upgrade <em>their</em> dependency on <code>collection</code> then everyone who upgrades <code>widgets</code> would have to as well, <em>whether they want to or not</em>. That's painful, so you end up with a disincentive to upgrade dependencies. That's called <strong>version lock</strong>: everyone wants to move their dependencies forward, but no one can take the first step because it forces everyone else to as well.</p><div class="header-wrapper"><h3 id="version-constraints-the-dart-approach">Version constraints (the Dart approach)</h3><a class="heading-link" href="#version-constraints-the-dart-approach" aria-label="Link to 'Version constraints (the Dart approach)' section">#</a></div><p>To solve version lock, we loosen the constraints that packages place on their dependencies. If <code>widgets</code> and <code>templates</code> can both indicate a <em>range</em> of versions for <code>collection</code> that they work with, then that gives us enough wiggle room to move our dependencies forward to newer versions. As long as there is overlap in their ranges, we can still find a single version that makes them both happy.</p><p>This is the model that <a href="https://bundler.io">bundler</a> follows, and is pub's model too. When you add a dependency in your pubspec, you can specify a <em>range</em> of versions that you can accept. If the pubspec for <code>widgets</code> looked like this:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> collection</span><span style="color:#222222">: </span><span style="color:#11796D">'>=2.3.5 <2.4.0'</span></span></code></pre></div></div><p>You could pick version <code>2.3.7</code> for <code>collection</code>. A single concrete version would satisfy constraints for both the <code>widgets</code> and <code>templates</code> packages.</p><div class="header-wrapper"><h2 id="semantic-versions">Semantic versions</h2><a class="heading-link" href="#semantic-versions" aria-label="Link to 'Semantic versions' section">#</a></div><p>When you add a dependency to your package, you'll sometimes want to specify a range of versions to allow. How do you know what range to pick? You need to be forward compatible, so ideally the range encompasses future versions that haven't been released yet. But how do you know your package is going to work with some new version that doesn't even exist yet?</p><p>To solve that, you need to agree on what a version number <em>means</em>. Imagine that the developers of a package you depend on say, "If we make any backwards incompatible change, then we promise to increment the major version number." If you trust them, then if you know your package works with <code>2.3.5</code> of theirs, you can rely on it working all the way up to <code>3.0.0</code>. You can set your range like:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> collection</span><span style="color:#222222">: </span><span style="color:#11796D">^2.3.5</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><span class="material-symbols" aria-hidden="true">info</span> <span>Note</span></div><div class="alert-content"><p>This example uses <em>caret syntax</em> to express a range of versions. The string <code>^2.3.5</code> means "the range of all versions from 2.3.5 to 3.0.0, not including 3.0.0." To learn more, consult the <a href="/tools/pub/dependencies#caret-syntax">caret syntax</a> section.</p></div></aside><p>To make this work, then, we need to come up with that set of promises. Fortunately, other smart people have done the work of figuring this all out and named it <em><a href="https://semver.org/spec/v2.0.0-rc.1.html">semantic versioning</a></em>.</p><p>That describes the format of a version number, and the exact API behavioral differences when you increment to a later version number. Pub requires versions to be formatted that way, and to play well with the pub community, your package should follow the semantics it specifies. You should assume that the packages you depend on also follow it. (And if you find out they don't, let their authors know!)</p><p>Although semantic versioning doesn't promise any compatibility between versions prior to <code>1.0.0</code>, the Dart community convention is to treat those versions semantically as well. The interpretation of each number is just shifted down one slot: going from <code>0.1.2</code> to <code>0.2.0</code> indicates a breaking change, going to <code>0.1.3</code> indicates a new feature, and going to <code>0.1.2+1</code> indicates a change that doesn't affect the public API. For simplicity's sake, avoid using <code>+</code> after the version reaches <code>1.0.0</code>.</p><p>We've got almost all of the pieces we need to deal with versioning and API evolution now. Let's see how they play together and what pub does.</p><div class="header-wrapper"><h2 id="constraint-solving">Constraint solving</h2><a class="heading-link" href="#constraint-solving" aria-label="Link to 'Constraint solving' section">#</a></div><p>When you define your package, you list its <a href="/tools/pub/glossary#immediate-dependency">immediate dependencies</a>. These are packages that your package uses. For each of these package, you specify the range of versions your package allows. Each of those dependent packages might then have their own dependencies. These are called <a href="/tools/pub/glossary#transitive-dependency">transitive dependencies</a>. Pub traverses these and builds the entire dependency graph for your app.</p><p>For each package in the graph, pub looks at everything that depends on it. It gathers together all of their version constraints and tries to simultaneously solve them. Basically, it intersects their ranges. Then pub looks at the actual versions that have been released for that package and selects the most recent one that meets all of those constraints.</p><p>For example, let's say our dependency graph contains <code>collection</code>, and three packages depend on it. Their version constraints are:</p><div class="code-block-wrapper language-plaintext"><div class="code-block-body"><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span>>=1.7.0</span></span> <span class="line"><span>^1.4.0</span></span> <span class="line"><span><1.9.0</span></span></code></pre></div></div><p>The developers of <code>collection</code> have released these versions of it:</p><div class="code-block-wrapper language-plaintext"><div class="code-block-body"><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span>1.7.0</span></span> <span class="line"><span>1.7.1</span></span> <span class="line"><span>1.8.0</span></span> <span class="line"><span>1.8.1</span></span> <span class="line"><span>1.8.2</span></span> <span class="line"><span>1.9.0</span></span></code></pre></div></div><p>The highest version number that fits in all of those ranges is <code>1.8.2</code>, so pub picks that. That means your app <em>and every package your app uses</em> will all use <code>collection 1.8.2</code>.</p><div class="header-wrapper"><h2 id="constraint-context">Constraint context</h2><a class="heading-link" href="#constraint-context" aria-label="Link to 'Constraint context' section">#</a></div><p>The fact that selecting a package version takes into account <em>every</em> package that depends on it has an important consequence: <em>the specific version that will be selected for a package is a global property of the app using that package.</em></p><p>The following example shows what this means. Let's say we have two apps. Here are their pubspecs:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">my_app</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> widgets</span><span style="color:#222222">:</span></span></code></pre></div></div><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">other_app</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> widgets</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> collection</span><span style="color:#222222">: </span><span style="color:#11796D">'<1.5.0'</span></span></code></pre></div></div><p>They both depend on <code>widgets</code>, whose pubspec is:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">widgets</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> collection</span><span style="color:#222222">: </span><span style="color:#11796D">'>=1.0.0 <2.0.0'</span></span></code></pre></div></div><p>The <code>other_app</code> package depends directly on <code>collection</code> itself. The interesting part is that it happens to have a different version constraint on it than <code>widgets</code> does.</p><p>This means that you can't just look at the <code>widgets</code> package in isolation to figure out what version of <code>collection</code> it will use. It depends on the context. In <code>my_app</code>, <code>widgets</code> will use <code>collection 1.9.9</code>. But in <code>other_app</code>, <code>widgets</code> will get saddled with <code>collection 1.4.9</code> because of the <em>other</em> constraint that <code>otherapp</code> places on it.</p><p>This is why each app gets its own <code>package_config.json</code> file: The concrete version selected for each package depends on the entire dependency graph of the containing app.</p><div class="header-wrapper"><h2 id="constraint-solving-for-exported-dependencies">Constraint solving for exported dependencies</h2><a class="heading-link" href="#constraint-solving-for-exported-dependencies" aria-label="Link to 'Constraint solving for exported dependencies' section">#</a></div><p>Package authors must define package constraints with care. Consider the following scenario:</p><img src="/assets/img/tools/pub/PubExportedConstraints.png" alt="dependency graph"><p>The <code>bookshelf</code> package depends on <code>widgets</code>. The <code>widgets</code> package, currently at 1.2.0, exports <code>collection</code> via <code>export 'package:collection/collection.dart'</code>, and is at 2.4.0. The pubspec files are as follows:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">bookshelf</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> widgets</span><span style="color:#222222">: </span><span style="color:#11796D">^1.2.0</span></span></code></pre></div></div><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">widgets</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> collection</span><span style="color:#222222">: </span><span style="color:#11796D">^2.4.0</span></span></code></pre></div></div><p>The <code>collection</code> package is then updated to 2.5.0. The 2.5.0 version of <code>collection</code> includes a new method called <code>sortBackwards()</code>. <code>bookshelf</code> may call <code>sortBackwards()</code>, because it's part of the API exposed by <code>widgets</code>, despite <code>bookshelf</code> having only a transitive dependency on <code>collection</code>.</p><p>Because <code>widgets</code> has an API that is not reflected in its version number, the app that uses the <code>bookshelf</code> package and calls <code>sortBackwards()</code> may crash.</p><p>Exporting an API causes that API to be treated as if it is defined in the package itself, but it can't increase the version number when the API adds features. This means that <code>bookshelf</code> has no way of declaring that it needs a version of <code>widgets</code> that supports <code>sortBackwards()</code>.</p><p>For this reason, when dealing with exported packages, it's recommended that the package's author keeps a tighter limit on the upper and lower bounds of a dependency. In this case, the range for the <code>widgets</code> package should be narrowed:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">bookshelf</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> widgets</span><span style="color:#222222">: </span><span style="color:#11796D">'>=1.2.0 <1.3.0'</span></span></code></pre></div></div><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">widgets</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> collection</span><span style="color:#222222">: </span><span style="color:#11796D">'>=2.4.0 <2.5.0'</span></span></code></pre></div></div><p>This translates to a lower bound of 1.2.0 for <code>widgets</code> and 2.4.0 for <code>collection</code>. When someone releases the 2.5.0 version of <code>collection</code>, pub updates <code>widgets</code> to 1.3.0 and updates the corresponding constraints as well.</p><p>Using this convention ensures that users have the correct version of both packages, even if one is not a direct dependency.</p><div class="header-wrapper"><h2 id="lockfiles">Lockfiles</h2><a class="heading-link" href="#lockfiles" aria-label="Link to 'Lockfiles' section">#</a></div><p>So once pub has solved your app's version constraints, then what? The end result is a complete list of every package that your app depends on either directly or indirectly and the best version of that package that will work with your app's constraints.</p><p>For each package, pub takes that information, computes a <a href="/tools/pub/glossary#content-hashes">content hash</a> from it, and writes both to a <em><a href="/tools/pub/glossary#lockfile">lockfile</a></em> in your app's directory called <code>pubspec.lock</code>. When pub builds the <code>.dart_tool/package_config.json</code> file for your app, it uses the lockfile to know what versions of each package to refer to. (And if you're curious to see what versions it selected, you can read the lockfile to find out.)</p><p>The next important thing pub does is it <em>stops touching the lockfile</em>. Once you've got a lockfile for your app, pub won't touch it until you tell it to. This is important. It means you won't spontaneously start using new versions of random packages in your app without intending to. Once your app is locked, it stays locked until you manually tell it to update the lockfile.</p><p>If your package is for an app, you <em>check your lockfile into your source control system!</em> That way, everyone on your team will be using the exact same versions of every dependency when they build your app. You'll also use this when you deploy your app so you can ensure that your production servers are using the exact same packages that you're developing with.</p><div class="header-wrapper"><h2 id="when-things-go-wrong">When things go wrong</h2><a class="heading-link" href="#when-things-go-wrong" aria-label="Link to 'When things go wrong' section">#</a></div><p>Of course, all of this presumes that your dependency graph is perfect and flawless. Even with version ranges and pub's constraint solving and semantic versioning, you can never be entirely spared from the dangers of versionitis.</p><p>You might run into one of the following problems:</p><div class="header-wrapper"><h3 id="you-can-have-disjoint-constraints">You can have disjoint constraints</h3><a class="heading-link" href="#you-can-have-disjoint-constraints" aria-label="Link to 'You can have disjoint constraints' section">#</a></div><p>Lets say your app uses <code>widgets</code> and <code>templates</code> and both use <code>collection</code>. But <code>widgets</code> asks for a version of it between <code>1.0.0</code> and <code>2.0.0</code> and <code>templates</code> wants something between <code>3.0.0</code> and <code>4.0.0</code>. Those ranges don't even overlap. There's no possible version that would work.</p><div class="header-wrapper"><h3 id="you-can-have-ranges-that-dont-contain-a-released-version">You can have ranges that don't contain a released version</h3><a class="heading-link" href="#you-can-have-ranges-that-dont-contain-a-released-version" aria-label="Link to 'You can have ranges that don't contain a released version' section">#</a></div><p>Let's say after putting all of the constraints on a shared dependency together, you have a narrow range of <code>>=1.2.4 <1.2.6</code>. It's not an empty range. If there was a version <code>1.2.4</code> of the dependency, you'd be golden. But maybe they never released that version. Instead, they went straight from <code>1.2.3</code> to <code>1.3.0</code>. You've got a range with nothing inside it.</p><div class="header-wrapper"><h3 id="you-can-have-an-unstable-graph">You can have an unstable graph</h3><a class="heading-link" href="#you-can-have-an-unstable-graph" aria-label="Link to 'You can have an unstable graph' section">#</a></div><p>This is, by far, the most challenging part of pub's version solving process. The process was described as <em>build up the dependency graph and then solve all of the constraints and pick versions</em>. But it doesn't actually work that way. How could you build up the <em>whole</em> dependency graph before you've picked <em>any</em> versions? <em>The pubspecs themselves are version-specific.</em> Different versions of the same package may have different sets of dependencies.</p><p>As you're selecting versions of packages, they are changing the shape of the dependency graph itself. As the graph changes, that may change constraints, which can cause you to select different versions, and then you go right back around in a circle.</p><p>Sometimes this process never settles down into a stable solution. Gaze into the abyss:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">my_app</span></span> <span class="line"><span style="color:#0468D7">version</span><span style="color:#222222">: </span><span style="color:#11796D">0.0.0</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> yin</span><span style="color:#222222">: </span><span style="color:#11796D">'>=1.0.0'</span></span></code></pre></div></div><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">yin</span></span> <span class="line"><span style="color:#0468D7">version</span><span style="color:#222222">: </span><span style="color:#11796D">1.0.0</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span></code></pre></div></div><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">yin</span></span> <span class="line"><span style="color:#0468D7">version</span><span style="color:#222222">: </span><span style="color:#11796D">2.0.0</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> yang</span><span style="color:#222222">: </span><span style="color:#11796D">'1.0.0'</span></span></code></pre></div></div><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">name</span><span style="color:#222222">: </span><span style="color:#11796D">yang</span></span> <span class="line"><span style="color:#0468D7">version</span><span style="color:#222222">: </span><span style="color:#11796D">1.0.0</span></span> <span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> yin</span><span style="color:#222222">: </span><span style="color:#11796D">'1.0.0'</span></span></code></pre></div></div><p>In all of these cases, there is no set of concrete versions that will work for your app, and when this happens pub reports an error and tells you what's going on. It definitely won't leave you in some weird state where you think things can work but won't.</p><div class="header-wrapper"><h2 id="summary">Summary</h2><a class="heading-link" href="#summary" aria-label="Link to 'Summary' section">#</a></div><p>In summary:</p><ul><li>Though code reuse has advantages, packages require the ability to evolve independently.</li><li>Versioning enables that independence. Depending on single concrete versions lacks flexibility. Coupled with shared dependencies, it leads to version lock.</li><li>To cope with version lock, your package should depend on a <em>range</em> of versions. Pub then walks your dependency graph and picks the best versions for you. If it can't pick an appropriate version, pub alerts you.</li><li>Once your app has a solid set of versions for its dependencies, that set gets pinned down in a <em>lockfile</em>. That ensures that every machine running your app uses the same versions of all of its dependencies.</li></ul><p>To learn more about pub's version solving algorithm, consult the <a href="https://medium.com/@nex3/pubgrub-2fb6470504f">PubGrub</a> article on Medium.</p><p id="page-github-links"><span>Unless stated otherwise, the documentation on this site reflects Dart 3.7.0. Page last updated on 2024-11-18.</span> <a href="https://github.com/dart-lang/site-www/tree/main/src/content/tools/pub/versioning.md" target="_blank" rel="noopener">View source</a> <span>or </span><a href="https://github.com/dart-lang/site-www/issues/new?template=1_page_issue.yml&page-url=https://dart.dev/tools/pub/versioning/&page-source=https://github.com/dart-lang/site-www/tree/main/src/content/tools/pub/versioning.md" title="Report an issue with this page" target="_blank" rel="noopener">report an issue</a>.</p></div></article></main></div><footer id="page-footer"><div class="footer-section footer-main"><a href="/" class="brand" title="Dart"><img src="/assets/img/logo/logo-white-text.svg" alt="Dart" width="164"></a><div class="footer-social-links"><a href="https://medium.com/dartlang" target="_blank" rel="noopener" title="Dart's Medium publication"><svg><use href="/assets/img/social/medium.svg#medium"></use></svg> </a><a href="https://github.com/dart-lang" target="_blank" rel="noopener" title="Dart's GitHub organization"><svg><use href="/assets/img/social/github.svg#github"></use></svg> </a><a href="https://bsky.app/profile/dart.dev" target="_blank" rel="noopener" title="Dart's Bluesky profile"><svg><use href="/assets/img/social/bluesky.svg#bluesky"></use></svg> </a><a href="https://twitter.com/dart_lang" target="_blank" rel="noopener" title="Dart's X (Twitter) profile"><svg><use href="/assets/img/social/x.svg#x"></use></svg></a></div></div><div class="footer-section footer-tray"><div class="footer-licenses">Except as otherwise noted, this site is licensed under a <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>, and code samples are licensed under the <a href="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</a>.</div><div class="footer-utility-links"><ul><li><a href="/terms" title="Terms of use">Terms</a></li><li><a href="https://policies.google.com/privacy" target="_blank" rel="noopener" title="Privacy policy">Privacy</a></li><li><a href="/security" title="Security philosophy and practices">Security</a></li></ul></div></div></footer></div></body></html>