Udating the wizard to be less intrusive
diff --git a/action/config_wizard.go b/action/config_wizard.go
new file mode 100644
index 0000000..16886bb
--- /dev/null
+++ b/action/config_wizard.go
@@ -0,0 +1,362 @@
+package action
+
+import (
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"strings"
+
+	"github.com/Masterminds/glide/cache"
+	"github.com/Masterminds/glide/cfg"
+	"github.com/Masterminds/glide/msg"
+	gpath "github.com/Masterminds/glide/path"
+	"github.com/Masterminds/semver"
+	"github.com/Masterminds/vcs"
+)
+
+// ConfigWizard reads configuration from a glide.yaml file and attempts to suggest
+// improvements. The wizard is interactive.
+func ConfigWizard(base string) {
+	_, err := gpath.Glide()
+	glidefile := gpath.GlideFile
+	if err != nil {
+		msg.Info("Unable to find a glide.yaml file. Would you like to create one now? Yes (Y) or No (N)")
+		bres := msg.PromptUntilYorN()
+		if bres {
+			// Guess deps
+			conf := guessDeps(base, false)
+			// Write YAML
+			if err := conf.WriteFile(glidefile); err != nil {
+				msg.Die("Could not save %s: %s", glidefile, err)
+			}
+		} else {
+			msg.Err("Unable to find configuration file. Please create configuration information to continue.")
+		}
+	}
+
+	conf := EnsureConfig()
+
+	err = cache.Setup()
+	if err != nil {
+		msg.Die("Problem setting up cache: %s", err)
+	}
+
+	msg.Info("Looking for dependencies to make suggestions on")
+	msg.Info("--> Scanning for dependencies not using verion ranges")
+	msg.Info("--> Scanning for dependencies using commit ids")
+	var deps []*cfg.Dependency
+	for _, dep := range conf.Imports {
+		if wizardLookInto(dep) {
+			deps = append(deps, dep)
+		}
+	}
+
+	msg.Info("Gathering information on each dependency")
+	msg.Info("--> This may take a moment. Especially on a codebase with many dependencies")
+	msg.Info("--> Gathering release information for dependencies")
+	msg.Info("--> Looking for dependency imports where versions are commit ids")
+	for _, dep := range deps {
+		wizardFindVersions(dep)
+	}
+
+	var changes int
+	for _, dep := range deps {
+		var remote string
+		if dep.Repository != "" {
+			remote = dep.Repository
+		} else {
+			remote = "https://" + dep.Name
+		}
+
+		// First check, ask if the tag should be used instead of the commit id for it.
+		cur := cache.MemCurrent(remote)
+		if cur != "" && cur != dep.Reference {
+			wizardSugOnce()
+			var dres bool
+			asked, use, val := wizardOnce("current")
+			if !use {
+				dres = wizardAskCurrent(cur, dep)
+			}
+			if !asked {
+				as := wizardRemember()
+				wizardSetOnce("current", as, dres)
+			}
+
+			if asked && use {
+				dres = val.(bool)
+			}
+
+			if dres {
+				msg.Info("Updating %s to use the tag %s instead of commit id %s", dep.Name, cur, dep.Reference)
+				dep.Reference = cur
+				changes++
+			}
+		}
+
+		// Second check, if no version is being used and there's a semver release ask about latest.
+		memlatest := cache.MemLatest(remote)
+		if dep.Reference == "" && memlatest != "" {
+			wizardSugOnce()
+			var dres bool
+			asked, use, val := wizardOnce("latest")
+			if !use {
+				dres = wizardAskLatest(memlatest, dep)
+			}
+			if !asked {
+				as := wizardRemember()
+				wizardSetOnce("latest", as, dres)
+			}
+
+			if asked && use {
+				dres = val.(bool)
+			}
+
+			if dres {
+				msg.Info("Updating %s to use the release %s instead of no release", dep.Name, cur)
+				dep.Reference = cur
+				changes++
+			}
+		}
+
+		// Third check, if the version is semver offer to use a range instead.
+		sv, err := semver.NewVersion(dep.Reference)
+		if err == nil {
+			wizardSugOnce()
+			var res string
+			asked, use, val := wizardOnce("range")
+			if !use {
+				res = wizardAskRange(sv, dep)
+			}
+			if !asked {
+				as := wizardRemember()
+				wizardSetOnce("range", as, res)
+			}
+
+			if asked && use {
+				res = val.(string)
+			}
+
+			if res == "m" {
+				r := "^" + sv.String()
+				msg.Info("Updating %s to use the range %s instead of commit id %s", dep.Name, r, dep.Reference)
+				dep.Reference = r
+				changes++
+			} else if res == "p" {
+				r := "~" + sv.String()
+				msg.Info("Updating %s to use the range %s instead of commit id %s", dep.Name, r, dep.Reference)
+				dep.Reference = r
+				changes++
+			}
+		}
+	}
+
+	if changes > 0 {
+		msg.Info("Configuration changes have been made. Would you like to write these")
+		msg.Info("changes to your configuration file? Yes (Y) or No (N)")
+		dres := msg.PromptUntilYorN()
+		if dres {
+			msg.Info("Writing updates to configuration file (%s)", glidefile)
+			if err := conf.WriteFile(glidefile); err != nil {
+				msg.Die("Could not save %s: %s", glidefile, err)
+			}
+			msg.Info("You can now edit the glide.yaml file.:")
+			msg.Info("--> For more information on versions and ranges see https://glide.sh/docs/versions/")
+			msg.Info("--> For details on additional metadata see https://glide.sh/docs/glide.yaml/")
+		} else {
+			msg.Warn("Change not written to configuration file")
+		}
+	} else {
+		msg.Info("No proposed changes found. Have a nice day.")
+	}
+}
+
+var wizardOnceVal = make(map[string]interface{})
+var wizardOnceDo = make(map[string]bool)
+var wizardOnceAsked = make(map[string]bool)
+
+var wizardSuggeseOnce bool
+
+func wizardSugOnce() {
+	if !wizardSuggeseOnce {
+		msg.Info("Here are some suggestions...")
+	}
+	wizardSuggeseOnce = true
+}
+
+// Returns if it's you should prompt, if not prompt if you should use stored value,
+// and stored value if it has one.
+func wizardOnce(name string) (bool, bool, interface{}) {
+	return wizardOnceAsked[name], wizardOnceDo[name], wizardOnceVal[name]
+}
+
+func wizardSetOnce(name string, prompt bool, val interface{}) {
+	wizardOnceAsked[name] = true
+	wizardOnceDo[name] = prompt
+	wizardOnceVal[name] = val
+}
+
+func wizardRemember() bool {
+	msg.Info("Would you like to remember the previous decision and apply it to future")
+	msg.Info("dependencies? Yes (Y) or No (N)")
+	return msg.PromptUntilYorN()
+}
+
+func wizardAskRange(ver *semver.Version, d *cfg.Dependency) string {
+	vstr := ver.String()
+	msg.Info("The package %s appears to use semantic versions (http://semver.org).", d.Name)
+	msg.Info("Would you like to track the latest minor or patch releases (major.minor.path)?")
+	msg.Info("Tracking minor version releases would use '>= %s, < %d.0.0' ('^%s'). Tracking patch version", vstr, ver.Major()+1, vstr)
+	msg.Info("releases would use '>= %s, < %d.%d.0' ('~%s'). For more information on Glide versions", vstr, ver.Major(), ver.Minor()+1, vstr)
+	msg.Info("and ranges see https://glide.sh/docs/versions")
+	msg.Info("Minor (M), Patch (P), or Skip Ranges (S)?")
+	res, err := msg.PromptUntil([]string{"minor", "m", "patch", "p", "skip ranges", "s"})
+	if err != nil {
+		msg.Die("Error processing response: %s", err)
+	}
+	if res == "m" || res == "minor" {
+		return "m"
+	} else if res == "p" || res == "patch" {
+		return "p"
+	}
+
+	return "s"
+}
+
+func wizardAskCurrent(cur string, d *cfg.Dependency) bool {
+	msg.Info("The package %s is currently set to use the version %s.", d.Name, d.Reference)
+	msg.Info("There is an equivalent semantic version (http://semver.org) release of %s. Would", cur)
+	msg.Info("you like to use that instead? Yes (Y) or No (N)")
+	return msg.PromptUntilYorN()
+}
+
+func wizardAskLatest(latest string, d *cfg.Dependency) bool {
+	msg.Info("The package %s appears to have Semantic Version releases (http://semver.org). ", d.Name)
+	msg.Info("The latestrelease is %s. You are currently not using a release. Would you like", latest)
+	msg.Info("to use this release? Yes (Y) or No (N)")
+	return msg.PromptUntilYorN()
+}
+
+func wizardLookInto(d *cfg.Dependency) bool {
+	_, err := semver.NewConstraint(d.Reference)
+
+	// The existing version is already a valid semver constraint so we skip suggestions.
+	if err == nil {
+		return false
+	}
+
+	return true
+}
+
+// Note, this really needs a simpler name.
+var createGitParseVersion = regexp.MustCompile(`(?m-s)(?:tags)/(\S+)$`)
+
+func wizardFindVersions(d *cfg.Dependency) {
+	l, err := cache.Location()
+	if err != nil {
+		msg.Debug("Problem detecting cache location: %s", err)
+	}
+	var remote string
+	if d.Repository != "" {
+		remote = d.Repository
+	} else {
+		remote = "https://" + d.Name
+	}
+
+	key, err := cache.Key(remote)
+	if err != nil {
+		msg.Debug("Problem generating cache key for %s: %s", remote, err)
+	}
+
+	local := filepath.Join(l, "src", key)
+	repo, err := vcs.NewRepo(remote, local)
+	if err != nil {
+		msg.Debug("Problem getting repo instance: %s", err)
+	}
+
+	var useLocal bool
+	if _, err = os.Stat(local); err == nil {
+		useLocal = true
+	}
+
+	// Git endpoints allow for querying without fetching the codebase locally.
+	// We try that first to avoid fetching right away. Is this premature
+	// optimization?
+	cc := true
+	if !useLocal && repo.Vcs() == vcs.Git {
+		out, err2 := exec.Command("git", "ls-remote", remote).CombinedOutput()
+		if err2 == nil {
+			cache.MemTouch(remote)
+			cc = false
+			lines := strings.Split(string(out), "\n")
+			for _, i := range lines {
+				ti := strings.TrimSpace(i)
+				if found := createGitParseVersion.FindString(ti); found != "" {
+					tg := strings.TrimPrefix(strings.TrimSuffix(found, "^{}"), "tags/")
+					cache.MemPut(remote, tg)
+					if d.Reference != "" && strings.HasPrefix(ti, d.Reference) {
+						cache.MemSetCurrent(remote, tg)
+					}
+				}
+			}
+		}
+	}
+
+	if cc {
+		cache.Lock(key)
+		cache.MemTouch(remote)
+		if _, err = os.Stat(local); os.IsNotExist(err) {
+			repo.Get()
+			branch := findCurrentBranch(repo)
+			c := cache.RepoInfo{DefaultBranch: branch}
+			err = cache.SaveRepoData(key, c)
+			if err != nil {
+				msg.Debug("Error saving cache repo details: %s", err)
+			}
+		} else {
+			repo.Update()
+		}
+		tgs, err := repo.Tags()
+		if err != nil {
+			msg.Debug("Problem getting tags: %s", err)
+		} else {
+			for _, v := range tgs {
+				cache.MemPut(remote, v)
+			}
+		}
+		if d.Reference != "" && repo.IsReference(d.Reference) {
+			tgs, err = repo.TagsFromCommit(d.Reference)
+			if err != nil {
+				msg.Debug("Problem getting tags for commit: %s", err)
+			} else {
+				if len(tgs) > 0 {
+					for _, v := range tgs {
+						if !(repo.Vcs() == vcs.Hg && v == "tip") {
+							cache.MemSetCurrent(remote, v)
+						}
+					}
+				}
+			}
+		}
+		cache.Unlock(key)
+	}
+}
+
+func findCurrentBranch(repo vcs.Repo) string {
+	msg.Debug("Attempting to find current branch for %s", repo.Remote())
+	// Svn and Bzr don't have default branches.
+	if repo.Vcs() == vcs.Svn || repo.Vcs() == vcs.Bzr {
+		return ""
+	}
+
+	if repo.Vcs() == vcs.Git || repo.Vcs() == vcs.Hg {
+		ver, err := repo.Current()
+		if err != nil {
+			msg.Debug("Unable to find current branch for %s, error: %s", repo.Remote(), err)
+			return ""
+		}
+		return ver
+	}
+
+	return ""
+}
diff --git a/action/create.go b/action/create.go
index fa72e6b..4d1c0bb 100644
--- a/action/create.go
+++ b/action/create.go
@@ -2,31 +2,20 @@
 
 import (
 	"os"
-	"os/exec"
 	"path/filepath"
-	"regexp"
 	"sort"
 	"strings"
-	"sync"
 
-	"github.com/Masterminds/glide/cache"
 	"github.com/Masterminds/glide/cfg"
 	"github.com/Masterminds/glide/dependency"
 	"github.com/Masterminds/glide/gb"
 	"github.com/Masterminds/glide/godep"
-	"github.com/Masterminds/glide/gom"
 	"github.com/Masterminds/glide/gpm"
 	"github.com/Masterminds/glide/msg"
 	gpath "github.com/Masterminds/glide/path"
 	"github.com/Masterminds/glide/util"
-	"github.com/Masterminds/semver"
-	"github.com/Masterminds/vcs"
 )
 
-// TODO(mattfarina): This file could really use to be cleaned up. It's functional
-// but not all that elegant. This mess of code really needs someone to come
-// along and clean it up. Pretty please.
-
 // Create creates/initializes a new Glide repository.
 //
 // This will fail if a glide.yaml already exists.
@@ -36,21 +25,36 @@
 // If skipImport is set to true, this will not attempt to import from an existing
 // GPM, Godep, or GB project if one should exist. However, it will still attempt
 // to read the local source to determine required packages.
-func Create(base string, skipImport, noInteract, skipVerSug bool) {
+func Create(base string, skipImport, nonInteractive bool) {
 	glidefile := gpath.GlideFile
 	// Guard against overwrites.
 	guardYAML(glidefile)
 
 	// Guess deps
-	conf := guessDeps(base, skipImport, noInteract, skipVerSug)
+	conf := guessDeps(base, skipImport)
 	// Write YAML
-	msg.Info("Writing glide.yaml file")
+	msg.Info("Writing configuration file (%s)", glidefile)
 	if err := conf.WriteFile(glidefile); err != nil {
 		msg.Die("Could not save %s: %s", glidefile, err)
 	}
-	msg.Info("You can now edit the glide.yaml file. Consider:")
-	msg.Info("--> Using versions and ranges. See https://glide.sh/docs/versions/")
-	msg.Info("--> Adding additional metadata. See https://glide.sh/docs/glide.yaml/")
+
+	var res bool
+	if !nonInteractive {
+		msg.Info("Would you like Glide to help you find ways to improve your glide.yaml configuration?")
+		msg.Info("If you want to revisit this step you can use the config-wizard command at any time.")
+		msg.Info("Yes (Y) or No (N)?")
+		res = msg.PromptUntilYorN()
+		if res {
+			ConfigWizard(base)
+		}
+	}
+
+	if !res {
+		msg.Info("You can now edit the glide.yaml file. Consider:")
+		msg.Info("--> Using versions and ranges. See https://glide.sh/docs/versions/")
+		msg.Info("--> Adding additional metadata. See https://glide.sh/docs/glide.yaml/")
+		msg.Info("--> Running the config-wizard command to improve the versions in your configuration")
+	}
 }
 
 // guardYAML fails if the given file already exists.
@@ -69,7 +73,7 @@
 //
 // FIXME: This function is likely a one-off that has a more standard alternative.
 // It's also long and could use a refactor.
-func guessDeps(base string, skipImport, noInteract, skipVerSug bool) *cfg.Config {
+func guessDeps(base string, skipImport bool) *cfg.Config {
 	buildContext, err := util.GetBuildContext()
 	if err != nil {
 		msg.Die("Failed to build an import context: %s", err)
@@ -85,17 +89,18 @@
 
 	// Import by looking at other package managers and looking over the
 	// entire directory structure.
-	var deps cfg.Dependencies
 
 	// Attempt to import from other package managers.
 	if !skipImport {
-		deps = guessImportDeps(base)
-		if len(deps) == 0 {
-			msg.Info("No dependencies found to import")
-		}
+		guessImportDeps(base, config)
 	}
 
-	msg.Info("Scanning code to look for dependencies")
+	importLen := len(config.Imports)
+	if importLen == 0 {
+		msg.Info("Scanning code to look for dependencies")
+	} else {
+		msg.Info("Scanning code to look for dependencies not found in import")
+	}
 
 	// Resolve dependencies by looking at the tree.
 	r, err := dependency.NewResolver(base)
@@ -118,194 +123,39 @@
 		vpath = vpath + string(os.PathSeparator)
 	}
 
-	var count int
-	var all string
-	var allOnce bool
 	for _, pa := range sortable {
 		n := strings.TrimPrefix(pa, vpath)
 		root, subpkg := util.NormalizeName(n)
 
 		if !config.HasDependency(root) && root != config.Name {
-			count++
-			d := deps.Get(root)
-			if d == nil {
-				d = &cfg.Dependency{
-					Name: root,
-				}
-				msg.Info("--> Found reference to %s", n)
-			} else {
-				msg.Info("--> Found imported reference to %s", n)
+			msg.Info("--> Found reference to %s\n", n)
+			d := &cfg.Dependency{
+				Name: root,
 			}
-
-			all, allOnce = guessAskVersion(noInteract, all, allOnce, skipVerSug, d)
-
-			if subpkg != "" {
-				if !d.HasSubpackage(subpkg) {
-					d.Subpackages = append(d.Subpackages, subpkg)
-				}
-				msg.Verbose("--> Noting sub-package %s to %s", subpkg, root)
+			if len(subpkg) > 0 {
+				d.Subpackages = []string{subpkg}
 			}
-
 			config.Imports = append(config.Imports, d)
 		} else if config.HasDependency(root) {
 			if len(subpkg) > 0 {
 				subpkg = strings.TrimPrefix(subpkg, "/")
 				d := config.Imports.Get(root)
 				if !d.HasSubpackage(subpkg) {
+					msg.Info("--> Adding sub-package %s to %s\n", subpkg, root)
 					d.Subpackages = append(d.Subpackages, subpkg)
 				}
-				msg.Verbose("--> Noting sub-package %s to %s", subpkg, root)
 			}
 		}
 	}
 
-	if !skipImport && len(deps) > count {
-		var res string
-		if noInteract {
-			res = "y"
-		} else {
-			msg.Info("%d unused imported dependencies found. These are likely transitive dependencies ", len(deps)-count)
-			msg.Info("(dependencies of your dependencies). Would you like to track them in your")
-			msg.Info("glide.yaml file? Note, Glide will automatically scan your codebase to detect")
-			msg.Info("the complete dependency tree and import the complete tree. If your dependencies")
-			msg.Info("do not track dependency version information some version information may be lost.")
-			msg.Info("Yes (Y) or No (N)?")
-			res, err = msg.PromptUntil([]string{"y", "yes", "n", "no"})
-			if err != nil {
-				msg.Die("Error processing response: %s", err)
-			}
-		}
-		if res == "y" || res == "yes" {
-			msg.Info("Including additional imports in the glide.yaml file")
-			for _, dep := range deps {
-				found := config.Imports.Get(dep.Name)
-				if found == nil {
-					config.Imports = append(config.Imports, dep)
-					if dep.Reference != "" {
-						all, allOnce = guessAskVersion(noInteract, all, allOnce, skipVerSug, dep)
-						msg.Info("--> Adding %s at version %s", dep.Name, dep.Reference)
-					} else {
-						msg.Info("--> Adding %s", dep.Name)
-					}
-				}
-			}
-		}
+	if len(config.Imports) == importLen && importLen != 0 {
+		msg.Info("--> Code scanning found no additional imports")
 	}
 
 	return config
 }
 
-func guessAskVersion(noInteract bool, all string, allonce, skipVerSug bool, d *cfg.Dependency) (string, bool) {
-	if !noInteract && !skipVerSug && d.Reference == "" {
-		// If scanning has not happened already, for example this isn't an
-		// import, try it now.
-		var loc string
-		if d.Repository != "" {
-			loc = d.Repository
-		} else {
-			loc = "https://" + d.Name
-		}
-		if !guessVersionCache.checked(loc) {
-			createGuessVersion(loc, d.Reference)
-		}
-
-		semv := guessVersionCache.get(loc)
-		if semv != "" {
-			msg.Info("The package %s appears to have Semantic Version releases. The latest", d.Name)
-			msg.Info("release is %s. Would you like to use this release? Yes (Y) or No (N)", semv)
-			res, err2 := msg.PromptUntil([]string{"y", "yes", "n", "no"})
-			if err2 != nil {
-				msg.Die("Error processing response: %s", err2)
-			}
-
-			if res == "y" || res == "yes" {
-				d.Reference = semv
-			}
-		}
-
-	}
-
-	if !noInteract && d.Reference != "" {
-		var changedVer bool
-		ver, err := semver.NewVersion(d.Reference)
-		if err != nil && !skipVerSug {
-			var loc string
-			if d.Repository != "" {
-				loc = d.Repository
-			} else {
-				loc = "https://" + d.Name
-			}
-
-			semv := guessVersionCache.get(loc)
-			if semv != "" {
-				msg.Info("The package %s appears to have Semantic Version releases but the imported data", d.Name)
-				msg.Info("is not using them. The latest release is %s but the imported data is using %s.", semv, d.Reference)
-				msg.Info("Would you like to use the latest release version instead? Yes (Y) or No (N)")
-				res, err2 := msg.PromptUntil([]string{"y", "yes", "n", "no"})
-				if err2 != nil {
-					msg.Die("Error processing response: %s", err2)
-				}
-
-				if res == "y" || res == "yes" {
-					d.Reference = semv
-					changedVer = true
-				}
-			}
-		}
-
-		if changedVer {
-			ver, err = semver.NewVersion(d.Reference)
-		}
-		if err == nil {
-			if all == "" {
-				vstr := ver.String()
-				msg.Info("Imported dependency %s (%s) appears to use semantic versions (http://semver.org).", d.Name, d.Reference)
-				msg.Info("Would you like Glide to track the latest minor or patch releases (major.minor.path)?")
-				msg.Info("Tracking minor version releases would use '>= %s, < %d.0.0' ('^%s'). Tracking patch version", vstr, ver.Major()+1, vstr)
-				msg.Info("releases would use '>= %s, < %d.%d.0' ('~%s'). For more information on Glide versions", vstr, ver.Major(), ver.Minor()+1, vstr)
-				msg.Info("and ranges see https://glide.sh/docs/versions")
-				msg.Info("Minor (M), Patch (P), or Skip Ranges (S)?")
-				res, err := msg.PromptUntil([]string{"minor", "m", "patch", "p", "skip ranges", "s"})
-				if err != nil {
-					msg.Die("Error processing response: %s", err)
-				}
-				if res == "m" || res == "minor" {
-					d.Reference = "^" + vstr
-				} else if res == "p" || res == "patch" {
-					d.Reference = "~" + vstr
-				}
-
-				if !allonce {
-					msg.Info("Would you like to same response (%s) for future dependencies? Yes (Y) or No (N)", res)
-					res2, err := msg.PromptUntil([]string{"y", "yes", "n", "no"})
-					if err != nil {
-						msg.Die("Error processing response: %s", err)
-					}
-					if res2 == "yes" || res2 == "y" {
-						return res, true
-					}
-
-					return "", true
-				}
-
-			} else {
-				if all == "m" || all == "minor" {
-					d.Reference = "^" + ver.String()
-				} else if all == "p" || all == "patch" {
-					d.Reference = "~" + ver.String()
-				}
-			}
-
-			return all, allonce
-		}
-
-		return all, allonce
-	}
-
-	return all, allonce
-}
-
-func guessImportDeps(base string) cfg.Dependencies {
+func guessImportDeps(base string, config *cfg.Config) {
 	msg.Info("Attempting to import from other package managers (use --skip-import to skip)")
 	deps := []*cfg.Dependency{}
 	absBase, err := filepath.Abs(base)
@@ -315,7 +165,7 @@
 
 	if d, ok := guessImportGodep(absBase); ok {
 		msg.Info("Importing Godep configuration")
-		msg.Warn("--> Godep uses commit id versions. Consider using Semantic Versions with Glide")
+		msg.Warn("Godep uses commit id versions. Consider using Semantic Versions with Glide")
 		deps = d
 	} else if d, ok := guessImportGPM(absBase); ok {
 		msg.Info("Importing GPM configuration")
@@ -323,41 +173,17 @@
 	} else if d, ok := guessImportGB(absBase); ok {
 		msg.Info("Importing GB configuration")
 		deps = d
-	} else if d, ok := guessImportGom(absBase); ok {
-		msg.Info("Importing GB configuration")
-		deps = d
 	}
 
-	if len(deps) > 0 {
-		msg.Info("--> Attempting to detect versions from imported commit ids")
-	}
-
-	var wg sync.WaitGroup
-
 	for _, i := range deps {
-		wg.Add(1)
-		go func(dep *cfg.Dependency) {
-			var remote string
-			if dep.Repository != "" {
-				remote = dep.Repository
-			} else {
-				remote = "https://" + dep.Name
-			}
-			ver := createGuessVersion(remote, dep.Reference)
-			if ver != dep.Reference {
-				msg.Verbose("--> Found imported reference to %s at version %s", dep.Name, ver)
-				dep.Reference = ver
-			}
+		if i.Reference == "" {
+			msg.Info("--> Found imported reference to %s", i.Name)
+		} else {
+			msg.Info("--> Found imported reference to %s at revision %s", i.Name, i.Reference)
+		}
 
-			msg.Debug("--> Found imported reference to %s at revision %s", dep.Name, dep.Reference)
-
-			wg.Done()
-		}(i)
+		config.Imports = append(config.Imports, i)
 	}
-
-	wg.Wait()
-
-	return deps
 }
 
 func guessImportGodep(dir string) ([]*cfg.Dependency, bool) {
@@ -386,165 +212,3 @@
 
 	return d, true
 }
-
-func guessImportGom(dir string) ([]*cfg.Dependency, bool) {
-	d, err := gom.Parse(dir)
-	if err != nil || len(d) == 0 {
-		return []*cfg.Dependency{}, false
-	}
-
-	return d, true
-}
-
-// Note, this really needs a simpler name.
-var createGitParseVersion = regexp.MustCompile(`(?m-s)(?:tags)/(\S+)$`)
-
-var guessVersionCache = newVersionCache()
-
-func createGuessVersion(remote, id string) string {
-	err := cache.Setup()
-	if err != nil {
-		msg.Debug("Problem setting up cache: %s", err)
-	}
-	l, err := cache.Location()
-	if err != nil {
-		msg.Debug("Problem detecting cache location: %s", err)
-	}
-	key, err := cache.Key(remote)
-	if err != nil {
-		msg.Debug("Problem generating cache key for %s: %s", remote, err)
-	}
-
-	local := filepath.Join(l, "src", key)
-	repo, err := vcs.NewRepo(remote, local)
-	if err != nil {
-		msg.Debug("Problem getting repo instance: %s", err)
-	}
-
-	// Git endpoints allow for querying without fetching the codebase locally.
-	// We try that first to avoid fetching right away. Is this premature
-	// optimization?
-	cc := true
-	if repo.Vcs() == vcs.Git {
-		out, err := exec.Command("git", "ls-remote", remote).CombinedOutput()
-		if err == nil {
-			guessVersionCache.touchChecked(remote)
-			cc = false
-			lines := strings.Split(string(out), "\n")
-			res := ""
-
-			// TODO(mattfarina): Detect if the found version is semver and use
-			// that one instead of the first found.
-			for _, i := range lines {
-				ti := strings.TrimSpace(i)
-				if found := createGitParseVersion.FindString(ti); found != "" {
-					tg := strings.TrimPrefix(strings.TrimSuffix(found, "^{}"), "tags/")
-					if strings.HasPrefix(ti, id) {
-						res = tg
-					}
-
-					ver, err := semver.NewVersion(tg)
-					if err == nil {
-						if guessVersionCache.get(remote) == "" {
-							guessVersionCache.put(remote, tg)
-						} else {
-							ver2, err := semver.NewVersion(guessVersionCache.get(remote))
-							if err == nil {
-								if ver.GreaterThan(ver2) {
-									guessVersionCache.put(remote, tg)
-								}
-							}
-						}
-					}
-				}
-			}
-
-			if res != "" {
-				return res
-			}
-		}
-	}
-
-	if cc {
-		cache.Lock(key)
-		if _, err = os.Stat(local); os.IsNotExist(err) {
-			repo.Get()
-			branch := findCurrentBranch(repo)
-			c := cache.RepoInfo{DefaultBranch: branch}
-			err = cache.SaveRepoData(key, c)
-			if err != nil {
-				msg.Debug("Error saving cache repo details: %s", err)
-			}
-		} else {
-			repo.Update()
-		}
-
-		tgs, err := repo.TagsFromCommit(id)
-		if err != nil {
-			msg.Debug("Problem getting tags for commit: %s", err)
-		}
-		cache.Unlock(key)
-		if len(tgs) > 0 {
-			return tgs[0]
-		}
-	}
-
-	return id
-}
-
-func findCurrentBranch(repo vcs.Repo) string {
-	msg.Debug("Attempting to find current branch for %s", repo.Remote())
-	// Svn and Bzr don't have default branches.
-	if repo.Vcs() == vcs.Svn || repo.Vcs() == vcs.Bzr {
-		return ""
-	}
-
-	if repo.Vcs() == vcs.Git || repo.Vcs() == vcs.Hg {
-		ver, err := repo.Current()
-		if err != nil {
-			msg.Debug("Unable to find current branch for %s, error: %s", repo.Remote(), err)
-			return ""
-		}
-		return ver
-	}
-
-	return ""
-}
-
-type versionCache struct {
-	sync.RWMutex
-	cache map[string]string
-	cd    map[string]bool
-}
-
-func newVersionCache() *versionCache {
-	return &versionCache{
-		cache: make(map[string]string),
-		cd:    make(map[string]bool),
-	}
-}
-
-func (v *versionCache) put(name, version string) {
-	v.Lock()
-	defer v.Unlock()
-	v.cache[name] = version
-	v.cd[name] = true
-}
-
-func (v *versionCache) checked(name string) bool {
-	v.RLock()
-	defer v.RUnlock()
-	return v.cd[name]
-}
-
-func (v *versionCache) touchChecked(name string) {
-	v.Lock()
-	defer v.Unlock()
-	v.cd[name] = true
-}
-
-func (v *versionCache) get(name string) string {
-	v.RLock()
-	defer v.RUnlock()
-	return v.cache[name]
-}
diff --git a/cache/memory.go b/cache/memory.go
new file mode 100644
index 0000000..ff2a0b8
--- /dev/null
+++ b/cache/memory.go
@@ -0,0 +1,137 @@
+package cache
+
+import (
+	"sync"
+
+	"github.com/Masterminds/glide/msg"
+	"github.com/Masterminds/semver"
+)
+
+// Provide an in memory cache of imported project information.
+
+var defaultMemCache = newMemCache()
+
+// MemPut put a version into the in memory cache for a name.
+// This will silently ignore non-semver and make sure the latest
+// is stored.
+func MemPut(name, version string) {
+	defaultMemCache.put(name, version)
+}
+
+// MemTouched returns true if the cache was touched for a name.
+func MemTouched(name string) bool {
+	return defaultMemCache.touched(name)
+}
+
+// MemTouch notes if a name has been looked at.
+func MemTouch(name string) {
+	defaultMemCache.touch(name)
+}
+
+// MemLatest returns the latest, that is most recent, semver release. This
+// may be a blank string if no put value
+func MemLatest(name string) string {
+	return defaultMemCache.getLatest(name)
+}
+
+// MemSetCurrent is used to set the current version in use.
+func MemSetCurrent(name, version string) {
+	defaultMemCache.setCurrent(name, version)
+}
+
+// MemCurrent is used to get the current version in use.
+func MemCurrent(name string) string {
+	return defaultMemCache.current(name)
+}
+
+// An in memory cache.
+type memCache struct {
+	sync.RWMutex
+	latest   map[string]string
+	t        map[string]bool
+	versions map[string][]string
+	c        map[string]string
+}
+
+func newMemCache() *memCache {
+	return &memCache{
+		latest:   make(map[string]string),
+		t:        make(map[string]bool),
+		versions: make(map[string][]string),
+		c:        make(map[string]string),
+	}
+}
+
+func (m *memCache) setCurrent(name, version string) {
+	m.Lock()
+	defer m.Unlock()
+
+	if m.c[name] == "" {
+		m.c[name] = version
+	} else {
+		// If we already have a version try to see if the new or old one is
+		// semver and use that one.
+		_, err := semver.NewVersion(m.c[name])
+		if err != nil {
+			_, err2 := semver.NewVersion(version)
+			if err2 == nil {
+				m.c[name] = version
+			}
+		}
+	}
+}
+
+func (m *memCache) current(name string) string {
+	m.RLock()
+	defer m.RUnlock()
+	return m.c[name]
+}
+
+func (m *memCache) put(name, version string) {
+	m.Lock()
+	defer m.Unlock()
+	m.t[name] = true
+	sv, err := semver.NewVersion(version)
+	if err != nil {
+		msg.Debug("Ignoring %s version %s: %s", name, version, err)
+		return
+	}
+
+	latest, found := m.latest[name]
+	if found {
+		lv, err := semver.NewVersion(latest)
+		if err != nil {
+			if sv.GreaterThan(lv) {
+				m.latest[name] = version
+			}
+		}
+	}
+
+	found = false
+	for _, v := range m.versions[name] {
+		if v == version {
+			found = true
+		}
+	}
+	if !found {
+		m.versions[name] = append(m.versions[name], version)
+	}
+}
+
+func (m *memCache) touch(name string) {
+	m.Lock()
+	defer m.Unlock()
+	m.t[name] = true
+}
+
+func (m *memCache) touched(name string) bool {
+	m.RLock()
+	defer m.RUnlock()
+	return m.t[name]
+}
+
+func (m *memCache) getLatest(name string) string {
+	m.RLock()
+	defer m.RUnlock()
+	return m.latest[name]
+}
diff --git a/glide.go b/glide.go
index 2e01e1c..5bd2894 100644
--- a/glide.go
+++ b/glide.go
@@ -154,13 +154,20 @@
 					Name:  "non-interactive",
 					Usage: "Disable interactive prompts.",
 				},
-				cli.BoolFlag{
-					Name:  "skip-version-suggestions",
-					Usage: "When imported commit ids are found that don't map to versions skip suggesting a version.",
-				},
 			},
 			Action: func(c *cli.Context) {
-				action.Create(".", c.Bool("skip-import"), c.Bool("non-interactive"), c.Bool("skip-version-suggestions"))
+				action.Create(".", c.Bool("skip-import"), c.Bool("non-interactive"))
+			},
+		},
+		{
+			Name:      "config-wizard",
+			ShortName: "cw",
+			Usage:     "Wizard that makes optional suggestions to improve config in a glide.yaml file.",
+			Description: `Glide will analyze a projects glide.yaml file and the imported
+		projects to find ways the glide.yaml file can potentially be improved. It
+		will then interactively make suggestions that you can skip or accept.`,
+			Action: func(c *cli.Context) {
+				action.ConfigWizard(".")
 			},
 		},
 		{
diff --git a/msg/msg.go b/msg/msg.go
index bb8b919..34213fd 100644
--- a/msg/msg.go
+++ b/msg/msg.go
@@ -287,3 +287,27 @@
 func PromptUntil(opts []string) (string, error) {
 	return Default.PromptUntil(opts)
 }
+
+// PromptUntilYorN provides a prompt until the user chooses yes or no. This is
+// not case sensitive and they can input other options such as Y or N.
+// In the response Yes is bool true and No is bool false.
+func (m *Messenger) PromptUntilYorN() bool {
+	res, err := m.PromptUntil([]string{"y", "yes", "n", "no"})
+	if err != nil {
+		m.Die("Error processing response: %s", err)
+	}
+
+	if res == "y" || res == "yes" {
+		return true
+	}
+
+	return false
+}
+
+// PromptUntilYorN provides a prompt until the user chooses yes or no. This is
+// not case sensitive and they can input other options such as Y or N.
+// In the response Yes is bool true and No is bool false.
+// Uses the default setup.
+func PromptUntilYorN() bool {
+	return Default.PromptUntilYorN()
+}