diff --git a/glide.lock b/glide.lock
index 3d3222867ddd50d4f9b9d5432a7c265af17d35a7..62620c5ded26d6461e28801b4c5ce280fdfcb974 100644
--- a/glide.lock
+++ b/glide.lock
@@ -228,4 +228,6 @@ imports:
   - term
 - name: github.com/streadway/simpleuuid
   version: 6617b501e485b77e61b98cd533aefff9e258b5a7
+- name: github.com/Masterminds/glide
+  version: 84607742b10f492430762d038e954236bbaf23f7
 devImports: []
diff --git a/glide.yaml b/glide.yaml
index 6b1ab4221fd9d4dfccf5d67eaea6e9ed43438e48..d832bc2213309b201c8c52bda69fbb9e87ef52f5 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -29,3 +29,5 @@ import:
 - package: github.com/Sirupsen/logrus
   version: ^0.11.0
 - package: github.com/streadway/simpleuuid
+- package: github.com/Masterminds/glide
+  version: ~0.12.3
\ No newline at end of file
diff --git a/util/hell/README.md b/util/hell/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8fe7fdb9ee299488204c8a9dda55a9b7542ce2dc
--- /dev/null
+++ b/util/hell/README.md
@@ -0,0 +1,4 @@
+> Hell is other people's packages
+
+While we wait for working package management in go we need a way to make
+maintaining the glide.lock by hand less painful.
\ No newline at end of file
diff --git a/util/hell/cmd/hell/main.go b/util/hell/cmd/hell/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..879bfdef528efb893e6fbedbbaff8eed603c92c4
--- /dev/null
+++ b/util/hell/cmd/hell/main.go
@@ -0,0 +1,117 @@
+package main
+
+import (
+	"fmt"
+	"os"
+
+	"path/filepath"
+
+	"github.com/Masterminds/glide/cache"
+	"github.com/Masterminds/glide/cfg"
+	"github.com/Masterminds/glide/msg"
+	"github.com/Masterminds/glide/path"
+	"github.com/Masterminds/glide/util"
+	"github.com/eris-ltd/eris-db/util/hell"
+	"github.com/spf13/cobra"
+	"github.com/Masterminds/glide/action"
+	"github.com/Masterminds/glide/repo"
+)
+
+func main() {
+	hellCmd := &cobra.Command{
+		Use:   "hell",
+		Short: "Hell makes the most of it being warm",
+		Long:  "",
+		Run:   func(cmd *cobra.Command, args []string) { cmd.Help() },
+	}
+
+	// Lock merge command
+	var baseGlideLockFile, depGlideLockFile string
+	lockMergeCmd := &cobra.Command{
+		Use:   "lock-merge",
+		Short: "Merge glide.lock files together",
+		Long: "This command merges two glide.lock files into a single one by copying all dependencies " +
+			"from a base glide.lock and an override glide.lock to an output glide.lock with dependencies " +
+			"from override taking precedence over those from base.",
+		Run: func(cmd *cobra.Command, args []string) {
+			baseLockFile, err := cfg.ReadLockFile(baseGlideLockFile)
+			if err != nil {
+				fmt.Printf("Could not read file: %s\n", err)
+				os.Exit(1)
+			}
+			overrideLockFile, err := cfg.ReadLockFile(depGlideLockFile)
+			if err != nil {
+				fmt.Printf("Could not read file: %s\n", err)
+				os.Exit(1)
+			}
+			mergedLockFile, err := hell.MergeGlideLockFiles(baseLockFile, overrideLockFile)
+			if err != nil {
+				fmt.Printf("Could not merge lock files: %s\n", err)
+				os.Exit(1)
+			}
+			mergedBytes, err := mergedLockFile.Marshal()
+			if err != nil {
+				fmt.Printf("Could not marshal lock file: %s\n", err)
+				os.Exit(1)
+			}
+			os.Stdout.Write(mergedBytes)
+		},
+	}
+	lockMergeCmd.PersistentFlags().StringVarP(&baseGlideLockFile, "base", "b", "", "base lock file")
+	lockMergeCmd.PersistentFlags().StringVarP(&depGlideLockFile, "override", "o", "", "override lock file")
+
+	// Lock update
+	interactive := false
+	getTransitiveCmd := &cobra.Command{
+		Use:   "get",
+		Short: "gets a remote dependency to this project along with its transtive dependencies.",
+		Long: "Gets a remote dependency and its transitive dependencies by adding the remote " +
+			"depednency to this project's glide.yaml and merging the remote dependency's " +
+			"glide.lock into this project's glide.lock",
+		Run: func(cmd *cobra.Command, args []string) {
+			if len(args) != 1 {
+				msg.Die("%s requires a single argument of the remote dependency\n", cmd.Name())
+			}
+			rootPackage, _ := util.NormalizeName(args[0])
+			// Add dependency to glide
+			action.Get(args, repo.NewInstaller() , false, true, false, !interactive, false)
+			// Now hunt down the repo cache
+			dep := action.EnsureConfig().Imports.Get(rootPackage)
+			key, err := cache.Key(dep.Remote())
+			if err != nil {
+				msg.Die("%s requires a single argument of the remote dependency\n", cmd.Name())
+			}
+			cacheDir := filepath.Join(cache.Location(), "src", key)
+
+			if path.HasLock(cacheDir) {
+				msg.Info("Found dependency lock file, merging into project lock file")
+				lockPath := filepath.Join(".", path.LockFile)
+				baseLockFile, err := cfg.ReadLockFile(lockPath)
+				if err != nil {
+					msg.Die("Could not read base lock file: %s", err)
+				}
+				overrideLockFile, err := cfg.ReadLockFile(filepath.Join(cacheDir, path.LockFile))
+				if err != nil {
+					msg.Die("Could not read dependency lock file: %s", err)
+				}
+				mergedLockFile, err := hell.MergeGlideLockFiles(baseLockFile, overrideLockFile)
+				if err != nil {
+					msg.Die("Could not merge lock files: %s\n", err)
+				}
+				err = mergedLockFile.WriteFile(lockPath)
+				if err != nil {
+					msg.Die("Could not write merged lock file: %s", err)
+				}
+			} else {
+				msg.Info("Did not find dependency lock file, so nothing merged intoo project lock file")
+			}
+		},
+	}
+
+	getTransitiveCmd.PersistentFlags().BoolVarP(&interactive, "interactive", "i", false,
+		"set dependency verion interactively")
+
+	hellCmd.AddCommand(lockMergeCmd)
+	hellCmd.AddCommand(getTransitiveCmd)
+	lockMergeCmd.Execute()
+}
diff --git a/util/hell/merge.go b/util/hell/merge.go
new file mode 100644
index 0000000000000000000000000000000000000000..242d22af176eb084b0b41ae061e5b9b397883c47
--- /dev/null
+++ b/util/hell/merge.go
@@ -0,0 +1,88 @@
+package hell
+
+import (
+	"crypto/sha256"
+	"fmt"
+
+	"sort"
+
+	"github.com/Masterminds/glide/cfg"
+)
+
+// Merges two glide lock files together, letting dependencies from 'base' be overwritten
+// by those from 'override'. Returns the resultant glide lock file bytes
+func MergeGlideLockFiles(baseLockFile, overrideLockFile *cfg.Lockfile) (*cfg.Lockfile, error) {
+	imports := make(map[string]*cfg.Lock, len(baseLockFile.Imports))
+	devImports := make(map[string]*cfg.Lock, len(baseLockFile.DevImports))
+	// Copy the base dependencies into a map
+	for _, lock := range baseLockFile.Imports {
+		imports[lock.Name] = lock
+	}
+	for _, lock := range baseLockFile.DevImports {
+		devImports[lock.Name] = lock
+	}
+	// Override base dependencies and add any extra ones
+	for _, lock := range overrideLockFile.Imports {
+		imports[lock.Name] = mergeLocks(imports[lock.Name], lock)
+	}
+	for _, lock := range overrideLockFile.DevImports {
+		devImports[lock.Name] =  mergeLocks(imports[lock.Name], lock)
+	}
+
+	deps := make([]*cfg.Dependency, 0, len(imports))
+	devDeps := make([]*cfg.Dependency, 0, len(devImports))
+
+	// Flatten to Dependencies
+	for _, lock := range imports {
+		deps = append(deps, pinnedDependencyFromLock(lock))
+	}
+
+	for _, lock := range devImports {
+		devDeps = append(devDeps, pinnedDependencyFromLock(lock))
+	}
+
+	hasher := sha256.New()
+	hasher.Write(([]byte)(baseLockFile.Hash))
+	hasher.Write(([]byte)(overrideLockFile.Hash))
+
+	return cfg.NewLockfile(deps, devDeps, fmt.Sprintf("%x", hasher.Sum(nil)))
+}
+
+func mergeLocks(baseLock, overrideLock *cfg.Lock) *cfg.Lock {
+	lock := overrideLock.Clone()
+	if baseLock == nil {
+		return lock
+	}
+
+	// Merge and dedupe subpackages
+	subpackages := make([]string, 0, len(lock.Subpackages)+len(baseLock.Subpackages))
+	for _, sp := range lock.Subpackages {
+		subpackages = append(subpackages, sp)
+	}
+	for _, sp := range baseLock.Subpackages {
+		subpackages = append(subpackages, sp)
+	}
+
+	sort.Stable(sort.StringSlice(subpackages))
+
+	dedupeSubpackages := make([]string, 0, len(subpackages))
+
+	lastSp := ""
+	elided := 0
+	for _, sp := range subpackages {
+		if lastSp == sp {
+			elided++
+		} else {
+			dedupeSubpackages = append(dedupeSubpackages, sp)
+			lastSp = sp
+		}
+	}
+	lock.Subpackages = dedupeSubpackages[:len(dedupeSubpackages)-elided]
+	return lock
+}
+
+func pinnedDependencyFromLock(lock *cfg.Lock) *cfg.Dependency {
+	dep := cfg.DependencyFromLock(lock)
+	dep.Pin = lock.Version
+	return dep
+}
diff --git a/util/hell/merge_test.go b/util/hell/merge_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..cd59f4d07e309e87bdf2be42ec64528ca73d4a09
--- /dev/null
+++ b/util/hell/merge_test.go
@@ -0,0 +1,72 @@
+package hell
+
+import (
+	"testing"
+
+	"strings"
+
+	"github.com/Masterminds/glide/cfg"
+	"github.com/stretchr/testify/assert"
+)
+
+const baseLockYml = `imports:
+- name: github.com/gogo/protobuf
+  version: 82d16f734d6d871204a3feb1a73cb220cc92574c
+- name: github.com/tendermint/tendermint
+  version: aaea0c5d2e3ecfbf29f2608f9d43649ec7f07f50
+  subpackages:
+  - node
+  - proxy
+  - types
+  - version
+  - consensus
+  - rpc/core/types
+  - blockchain
+  - mempool
+  - rpc/core
+  - state
+`
+const overrideLockYml = `imports:
+- name: github.com/tendermint/tendermint
+  version: 764091dfbb035f1b28da4b067526e04c6a849966
+  subpackages:
+  - benchmarks
+  - proxy
+  - types
+  - version
+`
+const expectedLockYml = `imports:
+- name: github.com/gogo/protobuf
+  version: 82d16f734d6d871204a3feb1a73cb220cc92574c
+- name: github.com/tendermint/tendermint
+  version: 764091dfbb035f1b28da4b067526e04c6a849966
+  subpackages:
+  - benchmarks
+  - blockchain
+  - consensus
+  - mempool
+  - node
+  - proxy
+  - rpc/core
+  - rpc/core/types
+testImports: []
+`
+
+func TestMergeGlideLockFiles(t *testing.T) {
+	baseLockFile, err := cfg.LockfileFromYaml(([]byte)(baseLockYml))
+	assert.NoError(t, err, "Lockfile should parse")
+
+	overrideLockFile, err := cfg.LockfileFromYaml(([]byte)(overrideLockYml))
+	assert.NoError(t, err, "Lockfile should parse")
+
+	mergedLockFile, err := MergeGlideLockFiles(baseLockFile, overrideLockFile)
+	assert.NoError(t, err, "Lockfiles should merge")
+
+	mergedYmlBytes, err := mergedLockFile.Marshal()
+	assert.NoError(t, err, "Lockfile should marshal")
+
+	ymlLines := strings.Split(string(mergedYmlBytes), "\n")
+	// Drop the updated and hash lines
+	actualYml := strings.Join(ymlLines[2:], "\n")
+	assert.Equal(t, expectedLockYml, actualYml)
+}