How Glide Solves Go Vendoring
Glide is a practical tool for managing Go workspaces and dependencies in a sophisticated way, but without any sophisticated configuration.
This post shows by example how to use Glide.
Update: Added an example of private repositories.
Let's say I have a new Go project called
foo. Its full name will be
github.com/technosophos/foo. In my local development environment, I have a
foo which contains
To start up my Glide project, I do this:
$ cd foo $ glide create # Create a new glide.yaml file $ vi glide.yaml # edit my new YAML file $ glide in # start using Glide.
Above, we create a new
glide.yaml file, edit it, and then use
glide in to
set up all the important environment variables.
glide in command will configure the environment variables like
PATH so that your usual Go tools will all work in a predictable way.
(Strictly speaking, you don't
need to use
glide in to use Glide, but I find it helpful. You may
glide gopath to emit the GOPATH location.)
Now let's take a look at the YAML file.
A Basic glide.yaml
Glide uses a simple YAML configuration file to declare information about a given project. A bare-bones example looks something like this:
package: github.com/technosophos/foo import: - package: github.com/Masterminds/cookoo - package: github.com/aokoli/goutils
The above declares that our new project is called
and then declares that the project has two dependencies.
The first time you create a
glide.yaml file, you should run
$ glide install
glide install command will install the dependencies and configure the
workspace for working on this new
foo project. By default, it will create a
_vendor/ directory and use that to store local dependencies. But
installing requires the
glide.yaml file, so make sure you create that
From then on, you can keep your packages up to date with another command:
$ glide update
glide update will update packages. In the case above, it will update the local
packages to the latest revision. In a moment we'll see how to alter that
behavior. Both install and update will also intelligently build the libraries
into Go archive files (
foo.a), just like
go get and
go install do.
That's really all you need to get going with Glide. But here are some examples that show more of the features of Glide.
Above and beyond merely supporting basic dependency downloading and installing, glide also supports more sophisticated management.
Example 1: Use only a specific version of a package
Say we want to only use a specific version of a package. Let's say, for example,
that we want to use version
1.1.0 of Cookoo. We can easily do this by setting
an explicit reference:
package: github.com/technosophos/foo import: - package: github.com/Masterminds/cookoo ref: 1.1.0 vcs: git
This tells Glide to checkout the
1.1.0 tag from the git repository.
Glide can take commit numbers, tags, and branches in the
Example 2: Alias a repository
One thing that Go developers sometimes struggle with is the fact that
package names are coded into the
import statement. But when working
on, say, testing a git clone of a repository, you have to rewrite all of
your package's import statements.
Glide provides a simple way of working around this. With Glide, you can alias a VCS repo to another name:
- package: github.com/technosophos/foo repo: email@example.com:technosophos/foo vcs: git
In this case, Glide will check out a
bitbucket.org/technosophos/foo copy of
the repo, but configure it to act like
Go code that does
import "github.com/technosophos/foo" will actually
be using the bitbucket clone. Glide manages all of this for you...
without changing a single line of your Go code.
Example 3: Get a full repo, but only build part
Sometimes you need to
go get an entire repository, but you only plan
on using one or two pacakges. You can declare this intent like so:
- package: git.apache.org/thrift.git vcs: git ref: master repo: http://git.apache.org/thrift.git subpackages: - lib/go/thrift
The below checks out the entire Thrift source code, but only builds Go
archives for the subpackage
lib/go/thrift. Practically speaking, this
particular example mirrors the behavior of
go get. But because
subpackages can take multiple arguments you can optimize the behavior:
- package: github.com/crowdmob/goamz vcs: git ref: master subpackages: - aws - s3
This builds the
Example 4: Use a Private Repository
In addition to handling public repositories, Glide can handle private repositories, too.
Assuming that you can do a
git clone from your commandline, you can also
use Glide to handle a private repository:
- package: bitbucket.org/technosophos/foo repo: firstname.lastname@example.org:technosophos/foo vcs: git ref: feature/bar
The above will pull package
bitbucket.org/technosophos/foo from the
repository path specified in
Also in the example above, note that we're pulling from a different branch --
feature/bar instead of
master. This is certainly not required, but it is
Glide has two goals:
- Manage project-specific GOPATHs with dependencies stored in a local
- Manage package dependencies, including with versioning.
When these are done right, builds are reproducible, dependencies are stablized, and projects are isolated. This is better not only for ongoing development, but for the entire development-to-production lifecycle.
I've swapped Glide into just about every Go project I'm now working on, from small command-line clients to large servers with dozens and dozens of external package dependencies. It works.