Repository: readthedocs/readthedocs.org

Issue:
"Edit on Github" link broken by annotated tag
## Details

* Read the Docs project URL: https://osmnx.readthedocs.io/en/stable/
* Build URL (if applicable): https://github.com/gboeing/osmnx/
* Read the Docs username (if applicable): gboeing

## Expected Result

The "edit on Github" link at the top-right of the stable docs should point to the latest release.

## Actual Result

The [link](https://github.com/gboeing/osmnx/blob/685b9d0c7aac56ccd0ef3259515aa8404d254056/docs/source/index.rst) is broken. The problem seems to be how readthedocs uses the annotated tag that denotes the release. The link generated by readthedocs points to checksum `685b9d0` which is just an annotated tag that points to commit `902461a`. You can see this here:

```
$ git show 685b9d0c7aac56ccd0ef3259515aa8404d254056
tag v0.12
Tagger: gboeing <boeing@usc.edu>
Date:   Fri Apr 10 11:09:25 2020 -0700

v0.12

commit 902461ab8eb668732fa025c670057662fdd22039 (tag: v0.12)
Merge: bb1ef92 5ec6c2b
Author: Geoff Boeing <gboeing@users.noreply.github.com>
Date:   Fri Apr 10 11:06:56 2020 -0700

    Merge pull request #420 from gboeing/release
    
    v0.12 release
```

The [link](https://github.com/gboeing/osmnx/blob/685b9d0c7aac56ccd0ef3259515aa8404d254056/docs/source/index.rst) that readthedocs generates points to the annotated tag checksum, but that just leads you to a 404 page because you cannot browse at that point on Github. You [can](https://github.com/gboeing/osmnx/blob/902461ab8eb668732fa025c670057662fdd22039/docs/source/index.rst) only browse at the commit that the annotated tag points to. 

Related info from the [git docs](https://git-scm.com/book/en/v2/Git-Basics-Tagging):

> Git supports two types of tags: lightweight and annotated.
> 
> A lightweight tag is very much like a branch that doesn’t change — it’s just a pointer to a specific commit.
> 
> Annotated tags, however, are stored as full objects in the Git database. They’re checksummed; contain the tagger name, email, and date; have a tagging message; and can be signed and verified with GNU Privacy Guard (GPG). It’s generally recommended that you create annotated tags so you can have all this information



Discussion:
May be related to #1820 and #3302
This same broken-link problem is happening in other packages' stable docs, such as geopandas: https://geopandas.readthedocs.io/en/stable/ cc @jorisvandenbossche @martinfleis
This is a regression from https://github.com/readthedocs/readthedocs.org/pull/6651

`git.TagReference._iter_packed_refs` returns `('685b9d0c7aac56ccd0ef3259515aa8404d254056', 'refs/tags/v0.12')` and `tag.commit` returns the correct commit. I'll dig if there is a way around without having to revert that PR.

Resolving patch:
diff --git a/readthedocs/vcs_support/backends/git.py b/readthedocs/vcs_support/backends/git.py
--- a/readthedocs/vcs_support/backends/git.py
+++ b/readthedocs/vcs_support/backends/git.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
 """Git-related utilities."""
 
 import logging
@@ -7,6 +5,7 @@
 import re
 
 import git
+from gitdb.util import hex_to_bin
 from django.core.exceptions import ValidationError
 from git.exc import BadName, InvalidGitRepositoryError
 
@@ -207,8 +206,14 @@ def tags(self):
         # Build a cache of tag -> commit
         # GitPython is not very optimized for reading large numbers of tags
         ref_cache = {}  # 'ref/tags/<tag>' -> hexsha
+        # This code is the same that is executed for each tag in gitpython,
+        # we excute it only once for all tags.
         for hexsha, ref in git.TagReference._iter_packed_refs(repo):
-            ref_cache[ref] = hexsha
+            gitobject = git.Object.new_from_sha(repo, hex_to_bin(hexsha))
+            if gitobject.type == 'commit':
+                ref_cache[ref] = str(gitobject)
+            elif gitobject.type == 'tag' and gitobject.object.type == 'commit':
+                ref_cache[ref] = str(gitobject.object)
 
         for tag in repo.tags:
             if tag.path in ref_cache:


Test patch: