diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index f2828ecf215330977f05c61119b1e33ae5c96c47..57f806a14af74b18b587438eab3041b827c7fc01 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -14,6 +14,7 @@ import 'io.dart';
 import 'lock_file.dart';
 import 'log.dart' as log;
 import 'package.dart';
+import 'pubspec.dart';
 import 'system_cache.dart';
 import 'solver/version_solver.dart';
 import 'source/cached.dart';
@@ -68,8 +69,8 @@ class GlobalPackages {
       // Call this just to log what the current active package is, if any.
       _describeActive(name);
 
-      var id = new PackageId(name, "git", Version.none, repo);
-      return _installInCache(id);
+      return _installInCache(
+          new PackageDep(name, "git", VersionConstraint.any, repo));
     });
   }
 
@@ -77,24 +78,7 @@ class GlobalPackages {
   /// [constraint] and makes it the active global version.
   Future activateHosted(String name, VersionConstraint constraint) {
     _describeActive(name);
-
-    var source = cache.sources["hosted"];
-    return source.getVersions(name, name).then((versions) {
-      versions = versions.where(constraint.allows).toList();
-
-      if (versions.isEmpty) {
-        // TODO(rnystrom): Show most recent unmatching version?
-        dataError("Package ${log.bold(name)} has no versions that match "
-            "$constraint.");
-      }
-
-      // Pick the best matching version.
-      versions.sort(Version.prioritize);
-
-      // Make sure it's in the cache.
-      var id = new PackageId(name, "hosted", versions.last, name);
-      return _installInCache(id);
-    });
+    return _installInCache(new PackageDep(name, "hosted", constraint, name));
   }
 
   /// Makes the local package at [path] globally active.
@@ -112,36 +96,27 @@ class GlobalPackages {
       var fullPath = canonicalize(entrypoint.root.dir);
       var id = new PackageId(name, "path", entrypoint.root.version,
           PathSource.describePath(fullPath));
-      _writeLockFile(id, new LockFile.empty());
+      _writeLockFile(name, new LockFile([id]));
     });
   }
 
-  /// Installs the package [id] and its dependencies into the system cache.
-  Future _installInCache(PackageId id) {
-    var source = cache.sources[id.source];
+  /// Installs the package [dep] and its dependencies into the system cache.
+  Future _installInCache(PackageDep dep) {
+    var source = cache.sources[dep.source];
 
-    // Put the main package in the cache.
-    return source.downloadToSystemCache(id).then((package) {
-      // If we didn't know the version for the ID (which is true for Git
-      // packages), look it up now that we have it.
-      if (id.version == Version.none) {
-        id = id.atVersion(package.version);
-      }
+    // Create a dummy package with just [dep] so we can do resolution on it.
+    var root = new Package.inMemory(new Pubspec("pub global activate",
+        dependencies: [dep], sources: cache.sources));
 
-      return source.resolveId(id).then((id_) {
-        id = id_;
-
-        // Resolve it and download its dependencies.
-        return resolveVersions(SolveType.GET, cache.sources, package);
-      });
-    }).then((result) {
+    // Resolve it and download its dependencies.
+    return resolveVersions(SolveType.GET, cache.sources, root).then((result) {
       if (!result.succeeded) throw result.error;
       result.showReport(SolveType.GET);
 
       // Make sure all of the dependencies are locally installed.
       return Future.wait(result.packages.map(_cacheDependency));
     }).then((ids) {
-      _writeLockFile(id, new LockFile(ids));
+      _writeLockFile(dep.name, new LockFile(ids));
     });
   }
 
@@ -159,15 +134,13 @@ class GlobalPackages {
     }).then((_) => source.resolveId(id));
   }
 
-  /// Finishes activating package [id] by saving [lockFile] in the cache.
-  void _writeLockFile(PackageId id, LockFile lockFile) {
-    // Add the root package to the lockfile.
-    lockFile.packages[id.name] = id;
-
+  /// Finishes activating package [package] by saving [lockFile] in the cache.
+  void _writeLockFile(String package, LockFile lockFile) {
     ensureDir(_directory);
-    writeTextFile(_getLockFilePath(id.name),
+    writeTextFile(_getLockFilePath(package),
         lockFile.serialize(cache.rootDir, cache.sources));
 
+    var id = lockFile.packages[package];
     if (id.source == "git") {
       var url = GitSource.urlFromDescription(id.description);
       log.message('Activated ${log.bold(id.name)} ${id.version} from Git '
diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index 2ab26b21cdf4731023598d3124e9e0775b1f43c2..7aa573503dbd3d1127a07f07703530f8d6c678e7 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -266,11 +266,23 @@ class Pubspec {
         expectedName: expectedName, location: pubspecUri);
   }
 
-  Pubspec(this._name, this._version, this._dependencies, this._devDependencies,
-          this._dependencyOverrides, this._environment, this._transformers,
-          [Map fields])
-    : this.fields = fields == null ? new YamlMap() : fields,
-      _sources = null;
+  Pubspec(this._name, {Version version, Iterable<PackageDep> dependencies,
+          Iterable<PackageDep> devDependencies,
+          Iterable<PackageDep> dependencyOverrides,
+          VersionConstraint sdkConstraint,
+          Iterable<Iterable<TransformerConfig>> transformers,
+           Map fields, SourceRegistry sources})
+      : _version = version,
+        _dependencies = dependencies == null ? null : dependencies.toList(),
+        _devDependencies = devDependencies == null ? null :
+            devDependencies.toList(),
+        _dependencyOverrides = dependencyOverrides == null ? null :
+            dependencyOverrides.toList(),
+        _environment = new PubspecEnvironment(sdkConstraint),
+        _transformers = transformers == null ? [] :
+            transformers.map((phase) => phase.toSet()).toList(),
+        fields = fields == null ? new YamlMap() : new YamlMap.wrap(fields),
+        _sources = sources;
 
   Pubspec.empty()
     : _sources = null,
diff --git a/test/global/activate/supports_version_solver_backtracking_test.dart b/test/global/activate/supports_version_solver_backtracking_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1aa6f5c2030ffa8cd3789ce04796aa4ab5158eaf
--- /dev/null
+++ b/test/global/activate/supports_version_solver_backtracking_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('performs verison solver backtracking if necessary', () {
+    servePackages([
+      packageMap("foo", "1.1.0")..addAll({
+        "environment": {"sdk": ">=0.1.2 <0.2.0"}
+      }),
+      packageMap("foo", "1.2.0")..addAll({
+        "environment": {"sdk": ">=0.1.3 <0.2.0"}
+      }),
+    ]);
+
+    schedulePub(args: ["global", "activate", "foo"]);
+
+    // foo 1.2.0 won't be picked because its SDK constraint conflicts with the
+    // dummy SDK version 0.1.2+3.
+    d.dir(cachePath, [
+      d.dir('global_packages', [
+        d.matcherFile('foo.lock', contains('1.1.0'))
+      ])
+    ]).validate();
+  });
+}
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index de0d1135de5fdb45b1a6bb0014c9b123773fe560..d98a5bff0a875b18cb7cd7f58a7641b747111aa3 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -1462,10 +1462,12 @@ Package mockPackage(PackageId id, Map dependencyStrings, Map overrides) {
     });
   }
 
-  var pubspec = new Pubspec(id.name, id.version, dependencies,
-      devDependencies, dependencyOverrides,
-      new PubspecEnvironment(sdkConstraint), []);
-  return new Package.inMemory(pubspec);
+  return new Package.inMemory(new Pubspec(id.name,
+      version: id.version,
+      dependencies: dependencies,
+      devDependencies: devDependencies,
+      dependencyOverrides: dependencyOverrides,
+      sdkConstraint: sdkConstraint));
 }
 
 /// Creates a new [PackageId] parsed from [text], which looks something like