DUB supports two kinds of schemata for selecting package versions:

  1. SemVer based version identifiers (e.g. ">=1.0.0")
  2. Selection of a specific branch HEAD using the "~" prefix (e.g. "~master")

The rationale for supporting the latter is improving the situation for library developers. In particular it allows library developers to have their library checked out locally and be able to make and commit changes to the library while testing those changes in the context of a separate application package. Usually this would require making a new version tag for each change, which is not really practical. By referencing a certain branch of the library instead, this isn't necessary and development can happen nicely without unnecessary overhead. So far, so good.

However, all this has some unfortunate side effects. First, due to laziness or missing awareness many packages in the registry have no version tags at all, and, partially because of that, many public packages reference their dependencies by branch instead of by version. What this means is that any change on a branch of such a package can break an unknown amount of external code with no possibility for external packages to at least stay at a particular working commit.

The second issue is that this is prone to introducing version conflicts. If some library A correctly references library B by version (say >=1.0.3) and now the developer wants to develop library B in the context of some application A. To do so, application A, which also uses library A, references library B as ~master and the developer checks out the git repository of B and calls dub add-local on it. But now there is a conflict that generally cannot be easily or unambiguously resolved. Should the branch or the version constraint have precedence? Should this work for just ~master or any branch? What happens with >=1.0.0 vs. a ~2.0.x branch? There are arguments for and against either way - but no solution we encountered so far was ideal.

What finally occurred to us was the following simple, radical solution:

  1. Deprecate ~branch style dependencies and at some point finally completely remove support for them
  2. From now on, accept only packages for the registry if they contain at least a single version tag
  3. To still properly support development, allow the developer to override locally that a branch should be used for certain packages instead of the tagged version that would usually be used (either system globally for all projects, or on a per project basis)

Obligatory quote: Destroy!