Both Dart and Go support decentralized package distribution. One is able to directly adopt an existing git repository as dependency, easing the effort of distributing packages.

Sometimes we might expect more fine-grained control on what to pull from a git repository. For example, to lock a package’s version, we would specify a particular tag, commit or branch name to pull from. Or if it’s a mono-repo, we would choose a sub-directory from the repository root. This post summarizes how to achieve these purposes in both languages.

Dart

dart pub add has several options related to adding a git repository as dependency. To start with, one should specify the repository’s URL with the --git-url argument

dart pub add repo --git-url https://github.com/user/repo.git

This command adds a dependency named repo by pulling from https://github.com/user/repo.git. The --git-path argument can be provided to specify from which sub-directory of the repository dart should read from

dart pub add repo --git-url https://github.com/user/repo.git --git-path subdir/

Dart can also read from a specific git commit or branch (but not tags!), for which one should supply the --git-ref argument

dart pub add repo --git-url https://github.com/user/repo.git --git-path subdir/ --git-ref branch_name
# OR
dart pub add repo --git-url https://github.com/user/repo.git --git-path subdir/ --git-ref <commit-hash>

Go

Go modules are born to be based on git repositories. We regularly use go get to add a dependency

go get github.com/user/repo

, which pulls a remote repository, and parses its content as a Go module. A tag @vX.Y.Z can be suffixed to specify a particular git tag like

go get github.com/user/repo@vX.Y.Z

, which instead pulls from a tag named vX.Y.Z. There’s a detailed description on version tag’s semantics at Go Modules Reference - Versions. Straightforwardly, we can append its path after the repository’s name if a sub-directory is to be used

go get github.com/user/repo/subdir

Things become a little trickier when both sub-directory and tag are wanted. Literally, we might type a command as below

go get github.com/user/repo/subdir@vX.Y.Z

It, however, will fail with a complaint go: github.com/user/repo/subdir@vX.Y.Z: invalid version: unknown revision subdir/vX.Y.Z. What’s happening is, when a sub-directory is involved, Go modules will seek for a tag name with a pattern like subdir/vX.Y.Z, instead of aforementioned vX.Y.Z. This enables multiple sub-repos in a large mono-repo to individually tag their own version. We are hence required to rename the tag as subdir/vX.Y.Z, which should work as intended.

References