Repository: pypa/pip

Issue:
support git refs in @ syntax
We'd like to be able to put paths to gerrit reviews in requirements files.

Given a gerrit like https://review.openstack.org/#/c/345601/6, the path given for a git pull looks like:

   git pull https://git.openstack.org/openstack/oslo.db refs/changes/01/345601/6

pip syntax we'd expect would be:

```
.venv/bin/pip install -e git+https://git.openstack.org/openstack/oslo.db@refs/changes/01/345601/6#egg=oslo.db
```

current output:

```

Obtaining oslo.db from git+https://git.openstack.org/openstack/oslo.db@refs/changes/01/345601/6#egg=oslo.db
  Cloning https://git.openstack.org/openstack/oslo.db (to refs/changes/01/345601/6) to ./.venv/src/oslo.db
  Could not find a tag or branch 'refs/changes/01/345601/6', assuming commit.
error: pathspec 'refs/changes/01/345601/6' did not match any file(s) known to git.
Command "git checkout -q refs/changes/01/345601/6" failed with error code 1 in /home/classic/.venv/src/oslo.db
```



Discussion:
@sshnaidm Please use Github reactions. They're meant for exactly this.

Resolving patch:
diff --git a/pip/vcs/git.py b/pip/vcs/git.py
--- a/pip/vcs/git.py
+++ b/pip/vcs/git.py
@@ -92,7 +92,8 @@ def check_rev_options(self, rev, dest, rev_options):
             return [revisions[rev]]
         else:
             logger.warning(
-                "Could not find a tag or branch '%s', assuming commit.", rev,
+                "Could not find a tag or branch '%s', assuming commit or ref",
+                rev,
             )
             return rev_options
 
@@ -146,9 +147,14 @@ def obtain(self, dest):
                 # Only do a checkout if rev_options differs from HEAD
                 if not self.check_version(dest, rev_options):
                     self.run_command(
-                        ['checkout', '-q'] + rev_options,
+                        ['fetch', '-q', url] + rev_options,
                         cwd=dest,
                     )
+                    self.run_command(
+                        ['checkout', '-q', 'FETCH_HEAD'],
+                        cwd=dest,
+                    )
+
             #: repo may contain submodules
             self.update_submodules(dest)
 


Test patch:
diff --git a/tests/functional/test_install_vcs.py b/tests/functional/test_install_vcs.py
--- a/tests/functional/test_install_vcs.py
+++ b/tests/functional/test_install_vcs.py
@@ -103,6 +103,27 @@ def test_git_with_tag_name_as_revision(script):
     assert '0.1' in version.stdout
 
 
+@pytest.mark.network
+def test_git_with_ref_as_revision(script):
+    """
+    Git backend should be able to install from a ref
+    """
+    version_pkg_path = _create_test_package(script)
+    script.run(
+        'git', 'update-ref', 'refs/foo/bar', 'HEAD',
+        expect_stderr=True,
+        cwd=version_pkg_path,
+    )
+    _change_test_package_version(script, version_pkg_path)
+    script.pip(
+        'install', '-e', '%s@refs/foo/bar#egg=version_pkg' %
+        ('git+file://' + version_pkg_path.abspath.replace('\\', '/')),
+        expect_stderr=True
+    )
+    version = script.run('version_pkg')
+    assert '0.1' in version.stdout
+
+
 @pytest.mark.network
 def test_git_with_tag_name_and_update(script, tmpdir):
     """