---
 title: Gopkg.lock
---

The `Gopkg.lock` file is generated by `dep ensure` and `dep init`. It is the output of [the solving function](ensure-mechanics.md#functional-flow): a transitively complete snapshot of a project's dependency graph, expressed as a series of `[[project]]` stanzas. That means:

* Every package a project needs to compile
* Plus any [`required`](Gopkg.toml.md#required) packages
* Less any [`ignored`](Gopkg.toml.md#ignored) packages

`Gopkg.lock` also contains some metadata about the algorithm and inputs used to arrive at the final graph, under `[solve-meta]`.

`Gopkg.lock` always includes a `revision` for all listed dependencies, as the semantics of `revision` guarantee them to be immutable. Thus, the `Gopkg.lock` acts as a reproducible build list - as long as the upstream remains available, all dependencies can be precisely reproduced.

`Gopkg.lock` is autogenerated; editing it manually is generally an antipattern. If there is a goal you can only achieve by hand-editing `Gopkg.lock`, it is at least a feature request, and likely a bug.

## `[[projects]]`

The dependency graph is expressed as a series of `[[projects]]` stanzas, each representing a single dependency project. A given project can only appear once in the list, and the version information expressed about them encompasses all contained packages - it is not possible to have multiple packages from a single project at different versions.

These are all the properties that can appear in a `[[projects]]` stanza, and whether or not they are guaranteed to be present/must be present for a stanza to be valid.

| **Property** | **Always present?** |
| ------------ | ------------------- |
| `name`       | Y                   |
| `packages`   | Y                   |
| `source`     | N                   |
| `revision`   | Y                   |
| `version`    | N                   |
| `branch`     | N                   |
| `pruneopts`  | Y                   |
| `digest`     | Y                   |

### `name`

The project to which the stanza applies, as identified by its [project root](glossary.md#project-root).

### `source`

If present, it indicates the upstream source from which the project should be retrieved. It has the same properties as [`source` in `Gopkg.toml`](Gopkg.toml.md#source).

### `packages`

A complete list of directories from within the source that dep determined to be necessary for the build.

In general, this is the set of packages that were found to be participants in the package import graph, through at least one but as many as all of the following mechanisms:

* Being in the current project's [`required`](Gopkg.toml.md#required) list
* Being imported by a package from either the current project or a different dependency
* Being imported by a package from within this project that, directly or transitively, is imported by a package from a different project

### `pruneopts`

A compactly-encoded form of the [prune options designated in `Gopkg.toml`](Gopkg.toml.md#prune) . Each character represents one of the three possible rules:

| Character | Pruning Rule in `Gopkg.toml` |
| --------- | ---------------------------- |
| `N`       | `non-go`                     |
| `U`       | `unused-packages`            |
| `T`       | `go-tests`                   |

If the character is present in `pruneopts`, the pruning rule is enabled for that project. Thus, `NUT` indicates that all three pruning rules are active.

### `digest`

The hash digest of the contents of `vendor/` for this project, _after_ pruning rules have been applied. The digest is versioned, by way of a colon-delimited prefix; the string is of the form `<version>:<hex-encoded digest>` . The hashing algorithm corresponding to version 1 is SHA256, as implemented in the stdlib package `crypto/sha256`.

There are some tweaks that differentiate the hasher apart from a naive filesystem tree hashing implementation:

* Symlinks are ignored.
* Line endings are normalized to LF (using an algorithm similar to git's) in order to ensure digests do not vary across platforms.

### Version information: `revision`, `version`, and `branch`

In order to provide reproducible builds, it is an absolute requirement that every project stanza contain a `revision`, no matter what kinds of constraints were encountered in `Gopkg.toml` files. It is further possible that exactly one of either `version` or `branch` will _additionally_ be present.

When one of the other two are present, the `revision` is understood to be the underlying, immutable identifier that corresponded to that `version` or `branch` _at the time when the `Gopkg.lock` was written_.

## `[solve-meta]`

Metadata contained in this section tells us about the algorithm that was used to generate the `Gopkg.lock` file. These are very coarse indicators, primarily used to trigger a re-evaluation of the lock when it might have become invalid, as well as warn a team when its members are using algorithms with potentially subtly different effects.

More details on "analyzer" and "solver" follow, but the versioning principle is the same: algorithmic changes that result in a decrease to the set of acceptable solutions for at least one input set generally require a version bump, while changes that increase the size of that set do not. However, this is not a formal definition; we leave room for judgment calls on small changes and bug fixes, and we bump at most once per release.

By bumping versions only on solution set contractions, but not expansions, it allows us to avoid having to bump constantly (which could make using dep across teams awkward), while still making it likely that when the solver and version numbers match between `Gopkg.lock` and a running version of dep, what's recorded in the file is acceptable by the running version's rules.

### `input-imports`

A sorted list of all the import inputs that were present at the time the `Gopkg.lock` was computed. This list includes both actual `import` statements from the project, as well as any `required` import paths listed in `Gopkg.toml`, excluding any that were `ignored`.

### `analyzer-name` and `analyzer-version`

The analyzer is an internal dep component responsible for interpreting the contents of `Gopkg.toml` files, as well as metadata files from any tools dep knows about: `glide.yaml`, `vendor.json`, etc.

The analyzer is named because the dep needs to identify itself to its engine, gps (`github.com/golang/dep/gps`); gps knows nothing about dep. The analyzer version is bumped when something in the analyzer's logic begins treating data that it already accepted in a significantly different way, or stops accepting a particular class of data. It is _not_ changed when support for entirely new types of data are added.

For example, if dep's analyzer stopped supporting automated conversions from glide, then that would not require bumping the analyzer version, as doing so makes _more_ solutions possible. Adding support for converting from a new tool, or changing the interpretation of `version` fields in `Gopkg.toml` so that it was only allowed to specify minimum versions, would entail a version bump.

### `solver-name` and `solver-version`

The solver is the algorithm behind [the solving function](ensure-mechanics.md#functional-flow). It selects all the versions that ultimately appear in `Gopkg.lock` by finding a combination that satisfies all the rules, including those from `Gopkg.toml` (fed to the solver by the analyzer).

The solver is named because, like the analyzer, it is pluggable; an alternative algorithm could be written that applies different rules to achieve the same goal. The one dep uses, "gps-cdcl", is named after [the general class of SAT solving algorithm it most resembles](https://en.wikipedia.org/wiki/Conflict-Driven_Clause_Learning), though the algorithm is actually a specialized, domain-specific [SMT solver](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories).

The same general principles of version-bumping apply to the solver version: if the solver starts enforcing [Go 1.4 import path comments](https://golang.org/cmd/go/#hdr-Import_path_checking), that entails a bump, because it can only narrow the solution set. If it were to later relax that requirement, it would not require a bump, as that can only expand the solution set.