Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build: Simplify and optimize git backend: New clone+fetch pattern #10430

Merged
merged 60 commits into from Jul 10, 2023

Conversation

benjaoming
Copy link
Contributor

@benjaoming benjaoming commented Jun 13, 2023

Fixes #9736

Still in draft mode. But we've discussed the approach and this seems to be the best compromise between reaching goals to make the process faster and not risking too much breakage.

  • Verify for branch builds
  • Verify for GitHub PR builds
  • Verify for tag builds
  • Update failing tests
  • Update tests that call old clone and fetch directly
  • Quick little benchmark example
  • Reverse the not on the feature flag
  • Add new test cases
  • Check code-base for where GitBackend.branches and GitBackend.tags is used. Old tests were assuming that it would return all branches after a clone. But we removed that by design, so this assumption has to be eliminated (we just need to force ls-remote then this is fine).
  • Special case fixed for stable versions (it's stored a version_type=TAG, but such a git tag doesn't exist) = we need to user Version.machine to be aware that it's an auto-generated version and use its commit hash to fetch.
  • Special case fixed for branches without a branch name. See details in "Default branches".
  • Manual Q&A w/ GitHub webhooks, sync branches for a fresh project
  • Remove the double-run of GitBackend tests, i.e. TestGitBackendTwiceInARow

High-level

  • The ways we invoke git clone and git fetch have been changed.
  • git clone no longer fetches branch and tag information, it just clones with minimal information and doesn't check out anything because we added --no-checkout. We know that we'll always call fetch afterwards and fetch exactly what's needed. We also know that we'll call git checkout (with a single known exception).
  • git fetch no longer contains --tags, meaning that it only fetches what is specified by the remote identifier.
  • New behavior is mostly hidden behind a feature flag (except for the new identifier argument for .update() VCS method)
  • Many cases that seem like they should be eliminated are identified with TODO comments. For instance, the new pattern still contains some legacy calls to make_clean_working_dir.
  • Eliminated calls to set_remote_url.
  • We should enable this on a few varied projects and perhaps get back in 1 month.

Changes: git clone

git clone fetches as little data as possible.

The new command is: git clone --no-checkout --depth 1 {repo_url} .

Changes: git fetch

git fetch doesn't have --tags anymore, and for branch and tag builds, it will now add the remote specifier for the branch or tag that is being fetched.

git fetch origin --force --prune --prune-tags --depth 50 {remote}

  • on branches, the remote uses: {Version.identifier}
  • on tags: refs/tags/{Version.verbose_name}:refs/tags/{Version.verbose_name}
  • on PRs: pull/{Version.verbose_name}/head:external-{Version.verbose_name}

Edit: I noticed that auto-created "stable" versions need special treatment because they are marked as a git tag. But we don't really know which branch the "stable" originates from because we throw away that information when setting "stable". So we'll have to keep fetching everything and then checking out the commit.

Note for default branches

For newly imported projects without a branch name set, a build is automatically started.

So we are building without any information about branch, tag or commit. We already have a mechanism that skips the "checkout" operation since we don't know what to check out.

It's quite easily solved, as the new clone operation automatically sits at the "HEAD" of the remote repo. But we need to remove --no-checkout from git clone in this case.

Example 🎉

➜ git clone --depth 1 https://github.com/readthedocs/tutorial-template.git .
Cloning into '.'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 14 (delta 0), reused 14 (delta 0), pack-reused 0
Receiving objects: 100% (14/14), 4.31 KiB | 4.31 MiB/s, done.

➜ git status
On branch main
Your branch is up to date with 'origin/main'.

Follow-ups

After these changes, our clone+fetch operations are likely so fast that no one should notice it, even big projects.

But there are some changes that can reduce the complexity in the codebase:

  • Create issue to eliminate feature flag in the future
  • Make sure that we store "stable" versions together with the actual tag or branch that they were found in. Use the information to fetch only what is required.
  • Get rid of --prune, --force, --prune-tags and other options that throw in strange assumptions that somehow the working directory isn't clean?
  • Reduce --depth 50 on git fetch
  • Trim down SyncRepositoryMixin.sync_versions to always use lsremote.
  • We can also remove GitBackend.branches and GitBackend.tags entirely, and make sure everything just uses lsremote.
  • ...and then remove the gitpython dependency.

@benjaoming
Copy link
Contributor Author

I've just discovered that Version.identifier contains commit hashes for tags and branch names for branches. I was a bit surprised to discover this. But then we cannot use it for the git fetch operations.

We need to rely on Version.verbose_name for now. It's already used for PRs, too, where the verbose_name is directly used to inject into remote references.

I don't think it's nice to have a property called "verbose" as if it's human readable and used this way. But I think it's pretty consistent to what already happened with PR numbers :)

@benjaoming benjaoming force-pushed the feature/git-clone-fetch-checkout branch from 4c1fe9b to b3af824 Compare June 14, 2023 10:14
@benjaoming
Copy link
Contributor Author

benjaoming commented Jun 14, 2023

Now that I think the clone and fetch methods look like they should, here's a test with a large repository (cpython):

git clone

Before: git clone --depth 50 --no-single-branch https://github.com/python/cpython

Total time: 90.6 seconds

Details

➜  test time git clone --depth 50 --no-single-branch https://github.com/python/cpython test-old-clone
Cloning into 'test-old-clone'...
remote: Enumerating objects: 285292, done.
remote: Counting objects: 100% (285292/285292), done.
remote: Compressing objects: 100% (105141/105141), done.
remote: Total 285292 (delta 222382), reused 236133 (delta 178026), pack-reused 0
Receiving objects: 100% (285292/285292), 296.37 MiB | 8.69 MiB/s, done.
Resolving deltas: 100% (222382/222382), done.
Checking connectivity: 285292, done.
git clone --depth 50 --no-single-branch https://github.com/python/cpython   41,42s user 4,85s system 51% cpu 1:30,60 total

After: git clone --depth 50 --no-single-branch https://github.com/python/cpython

Total time: 10.7 seconds

Details

time git clone --depth 1 --no-checkout https://github.com/python/cpython test-new-clone
Cloning into 'test-new-clone'...
remote: Enumerating objects: 4735, done.
remote: Counting objects: 100% (4735/4735), done.
remote: Compressing objects: 100% (4244/4244), done.
remote: Total 4735 (delta 496), reused 1760 (delta 331), pack-reused 0
Receiving objects: 100% (4735/4735), 25.89 MiB | 3.91 MiB/s, done.
Resolving deltas: 100% (496/496), done.
git clone --depth 1 --no-checkout https://github.com/python/cpython   1,45s user 0,42s system 17% cpu 10,792 total

git fetch

Before: git fetch origin --depth 50 --force --tags --prune --prune-tags

We are running this perhaps with an understanding that things already fetched during git clone will not be fetched again if we are using --depth 50 one more time. But I can only understand from experimentation that surely we ARE getting all these data one more time. Look at the object and delta counts. They are very close to the ones from the git clone command.

Total time: 92.3 seconds

Details

time git fetch origin --depth 50 --force --tags --prune --prune-tags
remote: Enumerating objects: 289814, done.
remote: Counting objects: 100% (268951/268951), done.
remote: Compressing objects: 100% (94537/94537), done.
remote: Total 255905 (delta 205592), reused 206375 (delta 159540), pack-reused 0
Receiving objects: 100% (255905/255905), 213.88 MiB | 11.34 MiB/s, done.
Resolving deltas: 100% (205592/205592), completed with 5037 local objects.
git fetch origin --depth 50 --force --tags --prune --prune-tags  41,57s user 4,11s system 49% cpu 1:32,38 total

After: git fetch origin --depth 50 --force --tags --prune --prune-tags main

Total time: 91.3s

For tags and branches, we are now adding a remote specifier to the fetch command. Most PRs have this, too (GitHub+GitLab). It doesn't make a big difference. I think that's because we have --tags (bad on large repos) and --depth 50 (makes it even worse)

Details

time git fetch origin --depth 50 --force --tags --prune --prune-tags main
remote: Enumerating objects: 283236, done.
remote: Counting objects: 100% (283236/283236), done.
remote: Compressing objects: 100% (103079/103079), done.
remote: Total 279797 (delta 223582), reused 227083 (delta 174753), pack-reused 0
Receiving objects: 100% (279797/279797), 260.08 MiB | 8.47 MiB/s, done.
Resolving deltas: 100% (223582/223582), completed with 2904 local objects.
From https://github.com/python/cpython
 * branch                  main         -> FETCH_HEAD
 * [new tag]               2.0          -> 2.0
 * [new tag]               2.1          -> 2.1
 * [new tag]               2.2          -> 2.2
 * [new tag]               2.3          -> 2.3
 * [new tag]               2.4          -> 2.4
 * [new tag]               2.5          -> 2.5
 * [new tag]               2.6          -> 2.6
 * [new tag]               2.7          -> 2.7
 * [new tag]               3.0          -> 3.0
 * [new tag]               3.1          -> 3.1
 * [new tag]               3.2          -> 3.2
 * [new tag]               3.3          -> 3.3
 * [new tag]               3.4          -> 3.4
 * [new tag]               3.5          -> 3.5
 * [new tag]               3.6          -> 3.6
 * [new tag]               legacy-trunk -> legacy-trunk
 * [new tag]               v0.9.8       -> v0.9.8
 * [new tag]               v0.9.9       -> v0.9.9
 * [new tag]               v1.0.1       -> v1.0.1
 * [new tag]               v1.0.2       -> v1.0.2
 * [new tag]               v1.1         -> v1.1
 * [new tag]               v1.1.1       -> v1.1.1
 * [new tag]               v1.2         -> v1.2
 * [new tag]               v1.2b1       -> v1.2b1
 * [new tag]               v1.2b2       -> v1.2b2
 * [new tag]               v1.2b3       -> v1.2b3
 * [new tag]               v1.2b4       -> v1.2b4
 * [new tag]               v1.3         -> v1.3
 * [new tag]               v1.3b1       -> v1.3b1
 * [new tag]               v1.4         -> v1.4
 * [new tag]               v1.4b1       -> v1.4b1
 * [new tag]               v1.4b2       -> v1.4b2
 * [new tag]               v1.4b3       -> v1.4b3
 * [new tag]               v1.5         -> v1.5
 * [new tag]               v1.5.1       -> v1.5.1
 * [new tag]               v1.5.2       -> v1.5.2
 * [new tag]               v1.5.2a1     -> v1.5.2a1
 * [new tag]               v1.5.2a2     -> v1.5.2a2
 * [new tag]               v1.5.2b1     -> v1.5.2b1
 * [new tag]               v1.5.2b2     -> v1.5.2b2
 * [new tag]               v1.5.2c1     -> v1.5.2c1
 * [new tag]               v1.5a1       -> v1.5a1
 * [new tag]               v1.5a2       -> v1.5a2
 * [new tag]               v1.5a3       -> v1.5a3
 * [new tag]               v1.5a4       -> v1.5a4
 * [new tag]               v1.5b1       -> v1.5b1
 * [new tag]               v1.5b2       -> v1.5b2
 * [new tag]               v1.6a1       -> v1.6a1
 * [new tag]               v1.6a2       -> v1.6a2
 * [new tag]               v2.0         -> v2.0
 * [new tag]               v2.0.1       -> v2.0.1
 * [new tag]               v2.0.1c1     -> v2.0.1c1
 * [new tag]               v2.0b1       -> v2.0b1
 * [new tag]               v2.0b2       -> v2.0b2
 * [new tag]               v2.0c1       -> v2.0c1
 * [new tag]               v2.1         -> v2.1
 * [new tag]               v2.1.1       -> v2.1.1
 * [new tag]               v2.1.1c1     -> v2.1.1c1
 * [new tag]               v2.1.2       -> v2.1.2
 * [new tag]               v2.1.2c1     -> v2.1.2c1
 * [new tag]               v2.1.3       -> v2.1.3
 * [new tag]               v2.1a1       -> v2.1a1
 * [new tag]               v2.1a2       -> v2.1a2
 * [new tag]               v2.1b1       -> v2.1b1
 * [new tag]               v2.1b2       -> v2.1b2
 * [new tag]               v2.1c1       -> v2.1c1
 * [new tag]               v2.1c2       -> v2.1c2
 * [new tag]               v2.2         -> v2.2
 * [new tag]               v2.2.1       -> v2.2.1
 * [new tag]               v2.2.1c1     -> v2.2.1c1
 * [new tag]               v2.2.1c2     -> v2.2.1c2
 * [new tag]               v2.2.2       -> v2.2.2
 * [new tag]               v2.2.2b1     -> v2.2.2b1
 * [new tag]               v2.2.3       -> v2.2.3
 * [new tag]               v2.2.3c1     -> v2.2.3c1
 * [new tag]               v2.2a3       -> v2.2a3
 * [new tag]               v2.3.1       -> v2.3.1
 * [new tag]               v2.3.2       -> v2.3.2
 * [new tag]               v2.3.2c1     -> v2.3.2c1
 * [new tag]               v2.3.3       -> v2.3.3
 * [new tag]               v2.3.3c1     -> v2.3.3c1
 * [new tag]               v2.3.4       -> v2.3.4
 * [new tag]               v2.3.4c1     -> v2.3.4c1
 * [new tag]               v2.3.5       -> v2.3.5
 * [new tag]               v2.3.5c1     -> v2.3.5c1
 * [new tag]               v2.3.6       -> v2.3.6
 * [new tag]               v2.3.6c1     -> v2.3.6c1
 * [new tag]               v2.3.7       -> v2.3.7
 * [new tag]               v2.3.7c1     -> v2.3.7c1
 * [new tag]               v2.3c1       -> v2.3c1
 * [new tag]               v2.3c2       -> v2.3c2
 * [new tag]               v2.4         -> v2.4
 * [new tag]               v2.4.1       -> v2.4.1
 * [new tag]               v2.4.1c1     -> v2.4.1c1
 * [new tag]               v2.4.1c2     -> v2.4.1c2
 * [new tag]               v2.4.2       -> v2.4.2
 * [new tag]               v2.4.2c1     -> v2.4.2c1
 * [new tag]               v2.4.3       -> v2.4.3
 * [new tag]               v2.4.3c1     -> v2.4.3c1
 * [new tag]               v2.4.4       -> v2.4.4
 * [new tag]               v2.4.4c1     -> v2.4.4c1
 * [new tag]               v2.4.5       -> v2.4.5
 * [new tag]               v2.4.5c1     -> v2.4.5c1
 * [new tag]               v2.4.6       -> v2.4.6
 * [new tag]               v2.4.6c1     -> v2.4.6c1
 * [new tag]               v2.4a1       -> v2.4a1
 * [new tag]               v2.4a2       -> v2.4a2
 * [new tag]               v2.4a3       -> v2.4a3
 * [new tag]               v2.4b1       -> v2.4b1
 * [new tag]               v2.4b2       -> v2.4b2
 * [new tag]               v2.4c1       -> v2.4c1
 * [new tag]               v2.5         -> v2.5
 * [new tag]               v2.5.1       -> v2.5.1
 * [new tag]               v2.5.1c1     -> v2.5.1c1
 * [new tag]               v2.5.2       -> v2.5.2
 * [new tag]               v2.5.2c1     -> v2.5.2c1
 * [new tag]               v2.5.3       -> v2.5.3
 * [new tag]               v2.5.3c1     -> v2.5.3c1
 * [new tag]               v2.5.4       -> v2.5.4
 * [new tag]               v2.5.5       -> v2.5.5
 * [new tag]               v2.5.5c1     -> v2.5.5c1
 * [new tag]               v2.5.5c2     -> v2.5.5c2
 * [new tag]               v2.5.6       -> v2.5.6
 * [new tag]               v2.5.6c1     -> v2.5.6c1
 * [new tag]               v2.5a0       -> v2.5a0
 * [new tag]               v2.5a1       -> v2.5a1
 * [new tag]               v2.5a2       -> v2.5a2
 * [new tag]               v2.5b1       -> v2.5b1
 * [new tag]               v2.5b2       -> v2.5b2
 * [new tag]               v2.5b3       -> v2.5b3
 * [new tag]               v2.5c1       -> v2.5c1
 * [new tag]               v2.5c2       -> v2.5c2
 * [new tag]               v2.6         -> v2.6
 * [new tag]               v2.6.1       -> v2.6.1
 * [new tag]               v2.6.2       -> v2.6.2
 * [new tag]               v2.6.2c1     -> v2.6.2c1
 * [new tag]               v2.6.3       -> v2.6.3
 * [new tag]               v2.6.3rc1    -> v2.6.3rc1
 * [new tag]               v2.6.4       -> v2.6.4
 * [new tag]               v2.6.4rc1    -> v2.6.4rc1
 * [new tag]               v2.6.4rc2    -> v2.6.4rc2
 * [new tag]               v2.6.5       -> v2.6.5
 * [new tag]               v2.6.5rc1    -> v2.6.5rc1
 * [new tag]               v2.6.5rc2    -> v2.6.5rc2
 * [new tag]               v2.6.6       -> v2.6.6
 * [new tag]               v2.6.6rc1    -> v2.6.6rc1
 * [new tag]               v2.6.6rc2    -> v2.6.6rc2
 * [new tag]               v2.6.7       -> v2.6.7
 * [new tag]               v2.6.8       -> v2.6.8
 * [new tag]               v2.6.8rc1    -> v2.6.8rc1
 * [new tag]               v2.6.8rc2    -> v2.6.8rc2
 * [new tag]               v2.6.9       -> v2.6.9
 * [new tag]               v2.6.9rc1    -> v2.6.9rc1
 * [new tag]               v2.6a1       -> v2.6a1
 * [new tag]               v2.6a2       -> v2.6a2
 * [new tag]               v2.6a3       -> v2.6a3
 * [new tag]               v2.6b1       -> v2.6b1
 * [new tag]               v2.6b2       -> v2.6b2
 * [new tag]               v2.6b3       -> v2.6b3
 * [new tag]               v2.6rc1      -> v2.6rc1
 * [new tag]               v2.6rc2      -> v2.6rc2
 * [new tag]               v2.7         -> v2.7
 * [new tag]               v2.7.1       -> v2.7.1
 * [new tag]               v2.7.10      -> v2.7.10
 * [new tag]               v2.7.10rc1   -> v2.7.10rc1
 * [new tag]               v2.7.11      -> v2.7.11
 * [new tag]               v2.7.11rc1   -> v2.7.11rc1
 * [new tag]               v2.7.12      -> v2.7.12
 * [new tag]               v2.7.12rc1   -> v2.7.12rc1
 * [new tag]               v2.7.13      -> v2.7.13
 * [new tag]               v2.7.13rc1   -> v2.7.13rc1
 * [new tag]               v2.7.14      -> v2.7.14
 * [new tag]               v2.7.14rc1   -> v2.7.14rc1
 * [new tag]               v2.7.15      -> v2.7.15
 * [new tag]               v2.7.15rc1   -> v2.7.15rc1
 * [new tag]               v2.7.16      -> v2.7.16
 * [new tag]               v2.7.16rc1   -> v2.7.16rc1
 * [new tag]               v2.7.17      -> v2.7.17
 * [new tag]               v2.7.17rc1   -> v2.7.17rc1
 * [new tag]               v2.7.18      -> v2.7.18
 * [new tag]               v2.7.18rc1   -> v2.7.18rc1
 * [new tag]               v2.7.1rc1    -> v2.7.1rc1
 * [new tag]               v2.7.2       -> v2.7.2
 * [new tag]               v2.7.2rc1    -> v2.7.2rc1
 * [new tag]               v2.7.3       -> v2.7.3
 * [new tag]               v2.7.3rc1    -> v2.7.3rc1
 * [new tag]               v2.7.3rc2    -> v2.7.3rc2
 * [new tag]               v2.7.4       -> v2.7.4
 * [new tag]               v2.7.4rc1    -> v2.7.4rc1
 * [new tag]               v2.7.5       -> v2.7.5
 * [new tag]               v2.7.6       -> v2.7.6
 * [new tag]               v2.7.6rc1    -> v2.7.6rc1
 * [new tag]               v2.7.7       -> v2.7.7
 * [new tag]               v2.7.7rc1    -> v2.7.7rc1
 * [new tag]               v2.7.8       -> v2.7.8
 * [new tag]               v2.7.9       -> v2.7.9
 * [new tag]               v2.7.9rc1    -> v2.7.9rc1
 * [new tag]               v2.7a1       -> v2.7a1
 * [new tag]               v2.7a2       -> v2.7a2
 * [new tag]               v2.7a3       -> v2.7a3
 * [new tag]               v2.7a4       -> v2.7a4
 * [new tag]               v2.7b1       -> v2.7b1
 * [new tag]               v2.7b2       -> v2.7b2
 * [new tag]               v2.7rc1      -> v2.7rc1
 * [new tag]               v2.7rc2      -> v2.7rc2
 * [new tag]               v3.0         -> v3.0
 * [new tag]               v3.0.1       -> v3.0.1
 * [new tag]               v3.0a1       -> v3.0a1
 * [new tag]               v3.0a2       -> v3.0a2
 * [new tag]               v3.0a3       -> v3.0a3
 * [new tag]               v3.0a4       -> v3.0a4
 * [new tag]               v3.0a5       -> v3.0a5
 * [new tag]               v3.0b1       -> v3.0b1
 * [new tag]               v3.0b2       -> v3.0b2
 * [new tag]               v3.0b3       -> v3.0b3
 * [new tag]               v3.0rc1      -> v3.0rc1
 * [new tag]               v3.0rc2      -> v3.0rc2
 * [new tag]               v3.0rc3      -> v3.0rc3
 * [new tag]               v3.1         -> v3.1
 * [new tag]               v3.1.1       -> v3.1.1
 * [new tag]               v3.1.1rc1    -> v3.1.1rc1
 * [new tag]               v3.1.2       -> v3.1.2
 * [new tag]               v3.1.2rc1    -> v3.1.2rc1
 * [new tag]               v3.1.3       -> v3.1.3
 * [new tag]               v3.1.3rc1    -> v3.1.3rc1
 * [new tag]               v3.1.4       -> v3.1.4
 * [new tag]               v3.1.4rc1    -> v3.1.4rc1
 * [new tag]               v3.1.5       -> v3.1.5
 * [new tag]               v3.1.5rc1    -> v3.1.5rc1
 * [new tag]               v3.1.5rc2    -> v3.1.5rc2
 * [new tag]               v3.10.0      -> v3.10.0
 * [new tag]               v3.10.0a1    -> v3.10.0a1
 * [new tag]               v3.10.0a2    -> v3.10.0a2
 * [new tag]               v3.10.0a3    -> v3.10.0a3
 * [new tag]               v3.10.0a4    -> v3.10.0a4
 * [new tag]               v3.10.0a5    -> v3.10.0a5
 * [new tag]               v3.10.0a6    -> v3.10.0a6
 * [new tag]               v3.10.0a7    -> v3.10.0a7
 * [new tag]               v3.10.0b1    -> v3.10.0b1
 * [new tag]               v3.10.0b2    -> v3.10.0b2
 * [new tag]               v3.10.0b3    -> v3.10.0b3
 * [new tag]               v3.10.0b4    -> v3.10.0b4
 * [new tag]               v3.10.0rc1   -> v3.10.0rc1
 * [new tag]               v3.10.0rc2   -> v3.10.0rc2
 * [new tag]               v3.10.1      -> v3.10.1
 * [new tag]               v3.10.10     -> v3.10.10
 * [new tag]               v3.10.11     -> v3.10.11
 * [new tag]               v3.10.12     -> v3.10.12
 * [new tag]               v3.10.2      -> v3.10.2
 * [new tag]               v3.10.3      -> v3.10.3
 * [new tag]               v3.10.4      -> v3.10.4
 * [new tag]               v3.10.5      -> v3.10.5
 * [new tag]               v3.10.6      -> v3.10.6
 * [new tag]               v3.10.7      -> v3.10.7
 * [new tag]               v3.10.8      -> v3.10.8
 * [new tag]               v3.10.9      -> v3.10.9
 * [new tag]               v3.11.0      -> v3.11.0
 * [new tag]               v3.11.0a1    -> v3.11.0a1
 * [new tag]               v3.11.0a2    -> v3.11.0a2
 * [new tag]               v3.11.0a3    -> v3.11.0a3
 * [new tag]               v3.11.0a4    -> v3.11.0a4
 * [new tag]               v3.11.0a5    -> v3.11.0a5
 * [new tag]               v3.11.0a6    -> v3.11.0a6
 * [new tag]               v3.11.0a7    -> v3.11.0a7
 * [new tag]               v3.11.0b1    -> v3.11.0b1
 * [new tag]               v3.11.0b2    -> v3.11.0b2
 * [new tag]               v3.11.0b3    -> v3.11.0b3
 * [new tag]               v3.11.0b4    -> v3.11.0b4
 * [new tag]               v3.11.0b5    -> v3.11.0b5
 * [new tag]               v3.11.0rc1   -> v3.11.0rc1
 * [new tag]               v3.11.0rc2   -> v3.11.0rc2
 * [new tag]               v3.11.1      -> v3.11.1
 * [new tag]               v3.11.2      -> v3.11.2
 * [new tag]               v3.11.3      -> v3.11.3
 * [new tag]               v3.11.4      -> v3.11.4
 * [new tag]               v3.12.0a1    -> v3.12.0a1
 * [new tag]               v3.12.0a2    -> v3.12.0a2
 * [new tag]               v3.12.0a3    -> v3.12.0a3
 * [new tag]               v3.12.0a4    -> v3.12.0a4
 * [new tag]               v3.12.0a5    -> v3.12.0a5
 * [new tag]               v3.12.0a6    -> v3.12.0a6
 * [new tag]               v3.12.0a7    -> v3.12.0a7
 * [new tag]               v3.12.0b1    -> v3.12.0b1
 * [new tag]               v3.12.0b2    -> v3.12.0b2
 * [new tag]               v3.1a1       -> v3.1a1
 * [new tag]               v3.1a2       -> v3.1a2
 * [new tag]               v3.1b1       -> v3.1b1
 * [new tag]               v3.1rc1      -> v3.1rc1
 * [new tag]               v3.1rc2      -> v3.1rc2
 * [new tag]               v3.2         -> v3.2
 * [new tag]               v3.2.1       -> v3.2.1
 * [new tag]               v3.2.1b1     -> v3.2.1b1
 * [new tag]               v3.2.1rc1    -> v3.2.1rc1
 * [new tag]               v3.2.1rc2    -> v3.2.1rc2
 * [new tag]               v3.2.2       -> v3.2.2
 * [new tag]               v3.2.2rc1    -> v3.2.2rc1
 * [new tag]               v3.2.3       -> v3.2.3
 * [new tag]               v3.2.3rc1    -> v3.2.3rc1
 * [new tag]               v3.2.3rc2    -> v3.2.3rc2
 * [new tag]               v3.2.4       -> v3.2.4
 * [new tag]               v3.2.4rc1    -> v3.2.4rc1
 * [new tag]               v3.2.5       -> v3.2.5
 * [new tag]               v3.2.6       -> v3.2.6
 * [new tag]               v3.2.6rc1    -> v3.2.6rc1
 * [new tag]               v3.2a1       -> v3.2a1
 * [new tag]               v3.2a2       -> v3.2a2
 * [new tag]               v3.2a3       -> v3.2a3
 * [new tag]               v3.2a4       -> v3.2a4
 * [new tag]               v3.2b1       -> v3.2b1
 * [new tag]               v3.2b2       -> v3.2b2
 * [new tag]               v3.2rc1      -> v3.2rc1
 * [new tag]               v3.2rc2      -> v3.2rc2
 * [new tag]               v3.2rc3      -> v3.2rc3
 * [new tag]               v3.3.0       -> v3.3.0
 * [new tag]               v3.3.0a1     -> v3.3.0a1
 * [new tag]               v3.3.0a2     -> v3.3.0a2
 * [new tag]               v3.3.0a3     -> v3.3.0a3
 * [new tag]               v3.3.0a4     -> v3.3.0a4
 * [new tag]               v3.3.0b1     -> v3.3.0b1
 * [new tag]               v3.3.0b2     -> v3.3.0b2
 * [new tag]               v3.3.0rc1    -> v3.3.0rc1
 * [new tag]               v3.3.0rc2    -> v3.3.0rc2
 * [new tag]               v3.3.0rc3    -> v3.3.0rc3
 * [new tag]               v3.3.1       -> v3.3.1
 * [new tag]               v3.3.1rc1    -> v3.3.1rc1
 * [new tag]               v3.3.2       -> v3.3.2
 * [new tag]               v3.3.3       -> v3.3.3
 * [new tag]               v3.3.3rc1    -> v3.3.3rc1
 * [new tag]               v3.3.3rc2    -> v3.3.3rc2
 * [new tag]               v3.3.4       -> v3.3.4
 * [new tag]               v3.3.4rc1    -> v3.3.4rc1
 * [new tag]               v3.3.5       -> v3.3.5
 * [new tag]               v3.3.5rc1    -> v3.3.5rc1
 * [new tag]               v3.3.5rc2    -> v3.3.5rc2
 * [new tag]               v3.3.6       -> v3.3.6
 * [new tag]               v3.3.6rc1    -> v3.3.6rc1
 * [new tag]               v3.3.7       -> v3.3.7
 * [new tag]               v3.3.7rc1    -> v3.3.7rc1
 * [new tag]               v3.4.0       -> v3.4.0
 * [new tag]               v3.4.0a1     -> v3.4.0a1
 * [new tag]               v3.4.0a2     -> v3.4.0a2
 * [new tag]               v3.4.0a3     -> v3.4.0a3
 * [new tag]               v3.4.0a4     -> v3.4.0a4
 * [new tag]               v3.4.0b1     -> v3.4.0b1
 * [new tag]               v3.4.0b2     -> v3.4.0b2
 * [new tag]               v3.4.0b3     -> v3.4.0b3
 * [new tag]               v3.4.0rc1    -> v3.4.0rc1
 * [new tag]               v3.4.0rc2    -> v3.4.0rc2
 * [new tag]               v3.4.0rc3    -> v3.4.0rc3
 * [new tag]               v3.4.1       -> v3.4.1
 * [new tag]               v3.4.10      -> v3.4.10
 * [new tag]               v3.4.10rc1   -> v3.4.10rc1
 * [new tag]               v3.4.1rc1    -> v3.4.1rc1
 * [new tag]               v3.4.2       -> v3.4.2
 * [new tag]               v3.4.2rc1    -> v3.4.2rc1
 * [new tag]               v3.4.3       -> v3.4.3
 * [new tag]               v3.4.3rc1    -> v3.4.3rc1
 * [new tag]               v3.4.4       -> v3.4.4
 * [new tag]               v3.4.4rc1    -> v3.4.4rc1
 * [new tag]               v3.4.5       -> v3.4.5
 * [new tag]               v3.4.5rc1    -> v3.4.5rc1
 * [new tag]               v3.4.6       -> v3.4.6
 * [new tag]               v3.4.6rc1    -> v3.4.6rc1
 * [new tag]               v3.4.7       -> v3.4.7
 * [new tag]               v3.4.7rc1    -> v3.4.7rc1
 * [new tag]               v3.4.8       -> v3.4.8
 * [new tag]               v3.4.8rc1    -> v3.4.8rc1
 * [new tag]               v3.4.9       -> v3.4.9
 * [new tag]               v3.4.9rc1    -> v3.4.9rc1
 * [new tag]               v3.5.0       -> v3.5.0
 * [new tag]               v3.5.0a1     -> v3.5.0a1
 * [new tag]               v3.5.0a2     -> v3.5.0a2
 * [new tag]               v3.5.0a3     -> v3.5.0a3
 * [new tag]               v3.5.0a4     -> v3.5.0a4
 * [new tag]               v3.5.0b1     -> v3.5.0b1
 * [new tag]               v3.5.0b2     -> v3.5.0b2
 * [new tag]               v3.5.0b3     -> v3.5.0b3
 * [new tag]               v3.5.0b4     -> v3.5.0b4
 * [new tag]               v3.5.0rc1    -> v3.5.0rc1
 * [new tag]               v3.5.0rc2    -> v3.5.0rc2
 * [new tag]               v3.5.0rc3    -> v3.5.0rc3
 * [new tag]               v3.5.0rc4    -> v3.5.0rc4
 * [new tag]               v3.5.1       -> v3.5.1
 * [new tag]               v3.5.10      -> v3.5.10
 * [new tag]               v3.5.10rc1   -> v3.5.10rc1
 * [new tag]               v3.5.1rc1    -> v3.5.1rc1
 * [new tag]               v3.5.2       -> v3.5.2
 * [new tag]               v3.5.2rc1    -> v3.5.2rc1
 * [new tag]               v3.5.3       -> v3.5.3
 * [new tag]               v3.5.3rc1    -> v3.5.3rc1
 * [new tag]               v3.5.4       -> v3.5.4
 * [new tag]               v3.5.4rc1    -> v3.5.4rc1
 * [new tag]               v3.5.5       -> v3.5.5
 * [new tag]               v3.5.5rc1    -> v3.5.5rc1
 * [new tag]               v3.5.6       -> v3.5.6
 * [new tag]               v3.5.6rc1    -> v3.5.6rc1
 * [new tag]               v3.5.7       -> v3.5.7
 * [new tag]               v3.5.7rc1    -> v3.5.7rc1
 * [new tag]               v3.5.8       -> v3.5.8
 * [new tag]               v3.5.8rc1    -> v3.5.8rc1
 * [new tag]               v3.5.8rc2    -> v3.5.8rc2
 * [new tag]               v3.5.9       -> v3.5.9
 * [new tag]               v3.6.0       -> v3.6.0
 * [new tag]               v3.6.0a1     -> v3.6.0a1
 * [new tag]               v3.6.0a2     -> v3.6.0a2
 * [new tag]               v3.6.0a3     -> v3.6.0a3
 * [new tag]               v3.6.0a4     -> v3.6.0a4
 * [new tag]               v3.6.0b1     -> v3.6.0b1
 * [new tag]               v3.6.0b2     -> v3.6.0b2
 * [new tag]               v3.6.0b3     -> v3.6.0b3
 * [new tag]               v3.6.0b4     -> v3.6.0b4
 * [new tag]               v3.6.0rc1    -> v3.6.0rc1
 * [new tag]               v3.6.0rc2    -> v3.6.0rc2
 * [new tag]               v3.6.1       -> v3.6.1
 * [new tag]               v3.6.10      -> v3.6.10
 * [new tag]               v3.6.10rc1   -> v3.6.10rc1
 * [new tag]               v3.6.11      -> v3.6.11
 * [new tag]               v3.6.11rc1   -> v3.6.11rc1
 * [new tag]               v3.6.12      -> v3.6.12
 * [new tag]               v3.6.13      -> v3.6.13
 * [new tag]               v3.6.14      -> v3.6.14
 * [new tag]               v3.6.15      -> v3.6.15
 * [new tag]               v3.6.1rc1    -> v3.6.1rc1
 * [new tag]               v3.6.2       -> v3.6.2
 * [new tag]               v3.6.2rc1    -> v3.6.2rc1
 * [new tag]               v3.6.2rc2    -> v3.6.2rc2
 * [new tag]               v3.6.3       -> v3.6.3
 * [new tag]               v3.6.3rc1    -> v3.6.3rc1
 * [new tag]               v3.6.4       -> v3.6.4
 * [new tag]               v3.6.4rc1    -> v3.6.4rc1
 * [new tag]               v3.6.5       -> v3.6.5
 * [new tag]               v3.6.5rc1    -> v3.6.5rc1
 * [new tag]               v3.6.6       -> v3.6.6
 * [new tag]               v3.6.6rc1    -> v3.6.6rc1
 * [new tag]               v3.6.7       -> v3.6.7
 * [new tag]               v3.6.7rc1    -> v3.6.7rc1
 * [new tag]               v3.6.7rc2    -> v3.6.7rc2
 * [new tag]               v3.6.8       -> v3.6.8
 * [new tag]               v3.6.8rc1    -> v3.6.8rc1
 * [new tag]               v3.6.9       -> v3.6.9
 * [new tag]               v3.6.9rc1    -> v3.6.9rc1
 * [new tag]               v3.7.0       -> v3.7.0
 * [new tag]               v3.7.0a1     -> v3.7.0a1
 * [new tag]               v3.7.0a2     -> v3.7.0a2
 * [new tag]               v3.7.0a3     -> v3.7.0a3
 * [new tag]               v3.7.0a4     -> v3.7.0a4
 * [new tag]               v3.7.0b1     -> v3.7.0b1
 * [new tag]               v3.7.0b2     -> v3.7.0b2
 * [new tag]               v3.7.0b3     -> v3.7.0b3
 * [new tag]               v3.7.0b4     -> v3.7.0b4
 * [new tag]               v3.7.0b5     -> v3.7.0b5
 * [new tag]               v3.7.0rc1    -> v3.7.0rc1
 * [new tag]               v3.7.1       -> v3.7.1
 * [new tag]               v3.7.10      -> v3.7.10
 * [new tag]               v3.7.11      -> v3.7.11
 * [new tag]               v3.7.12      -> v3.7.12
 * [new tag]               v3.7.13      -> v3.7.13
 * [new tag]               v3.7.14      -> v3.7.14
 * [new tag]               v3.7.15      -> v3.7.15
 * [new tag]               v3.7.16      -> v3.7.16
 * [new tag]               v3.7.17      -> v3.7.17
 * [new tag]               v3.7.1rc1    -> v3.7.1rc1
 * [new tag]               v3.7.1rc2    -> v3.7.1rc2
 * [new tag]               v3.7.2       -> v3.7.2
 * [new tag]               v3.7.2rc1    -> v3.7.2rc1
 * [new tag]               v3.7.3       -> v3.7.3
 * [new tag]               v3.7.3rc1    -> v3.7.3rc1
 * [new tag]               v3.7.4       -> v3.7.4
 * [new tag]               v3.7.4rc1    -> v3.7.4rc1
 * [new tag]               v3.7.4rc2    -> v3.7.4rc2
 * [new tag]               v3.7.5       -> v3.7.5
 * [new tag]               v3.7.5rc1    -> v3.7.5rc1
 * [new tag]               v3.7.6       -> v3.7.6
 * [new tag]               v3.7.6rc1    -> v3.7.6rc1
 * [new tag]               v3.7.7       -> v3.7.7
 * [new tag]               v3.7.7rc1    -> v3.7.7rc1
 * [new tag]               v3.7.8       -> v3.7.8
 * [new tag]               v3.7.8rc1    -> v3.7.8rc1
 * [new tag]               v3.7.9       -> v3.7.9
 * [new tag]               v3.8.0       -> v3.8.0
 * [new tag]               v3.8.0a1     -> v3.8.0a1
 * [new tag]               v3.8.0a2     -> v3.8.0a2
 * [new tag]               v3.8.0a3     -> v3.8.0a3
 * [new tag]               v3.8.0a4     -> v3.8.0a4
 * [new tag]               v3.8.0b1     -> v3.8.0b1
 * [new tag]               v3.8.0b2     -> v3.8.0b2
 * [new tag]               v3.8.0b3     -> v3.8.0b3
 * [new tag]               v3.8.0b4     -> v3.8.0b4
 * [new tag]               v3.8.0rc1    -> v3.8.0rc1
 * [new tag]               v3.8.1       -> v3.8.1
 * [new tag]               v3.8.10      -> v3.8.10
 * [new tag]               v3.8.11      -> v3.8.11
 * [new tag]               v3.8.12      -> v3.8.12
 * [new tag]               v3.8.13      -> v3.8.13
 * [new tag]               v3.8.14      -> v3.8.14
 * [new tag]               v3.8.15      -> v3.8.15
 * [new tag]               v3.8.16      -> v3.8.16
 * [new tag]               v3.8.17      -> v3.8.17
 * [new tag]               v3.8.1rc1    -> v3.8.1rc1
 * [new tag]               v3.8.2       -> v3.8.2
 * [new tag]               v3.8.2rc1    -> v3.8.2rc1
 * [new tag]               v3.8.2rc2    -> v3.8.2rc2
 * [new tag]               v3.8.3       -> v3.8.3
 * [new tag]               v3.8.3rc1    -> v3.8.3rc1
 * [new tag]               v3.8.4       -> v3.8.4
 * [new tag]               v3.8.4rc1    -> v3.8.4rc1
 * [new tag]               v3.8.5       -> v3.8.5
 * [new tag]               v3.8.6       -> v3.8.6
 * [new tag]               v3.8.6rc1    -> v3.8.6rc1
 * [new tag]               v3.8.7       -> v3.8.7
 * [new tag]               v3.8.7rc1    -> v3.8.7rc1
 * [new tag]               v3.8.8       -> v3.8.8
 * [new tag]               v3.8.8rc1    -> v3.8.8rc1
 * [new tag]               v3.8.9       -> v3.8.9
 * [new tag]               v3.9.0       -> v3.9.0
 * [new tag]               v3.9.0a1     -> v3.9.0a1
 * [new tag]               v3.9.0a2     -> v3.9.0a2
 * [new tag]               v3.9.0a3     -> v3.9.0a3
 * [new tag]               v3.9.0a4     -> v3.9.0a4
 * [new tag]               v3.9.0a5     -> v3.9.0a5
 * [new tag]               v3.9.0a6     -> v3.9.0a6
 * [new tag]               v3.9.0b1     -> v3.9.0b1
 * [new tag]               v3.9.0b2     -> v3.9.0b2
 * [new tag]               v3.9.0b3     -> v3.9.0b3
 * [new tag]               v3.9.0b4     -> v3.9.0b4
 * [new tag]               v3.9.0b5     -> v3.9.0b5
 * [new tag]               v3.9.0rc1    -> v3.9.0rc1
 * [new tag]               v3.9.0rc2    -> v3.9.0rc2
 * [new tag]               v3.9.1       -> v3.9.1
 * [new tag]               v3.9.10      -> v3.9.10
 * [new tag]               v3.9.11      -> v3.9.11
 * [new tag]               v3.9.12      -> v3.9.12
 * [new tag]               v3.9.13      -> v3.9.13
 * [new tag]               v3.9.14      -> v3.9.14
 * [new tag]               v3.9.15      -> v3.9.15
 * [new tag]               v3.9.16      -> v3.9.16
 * [new tag]               v3.9.17      -> v3.9.17
 * [new tag]               v3.9.1rc1    -> v3.9.1rc1
 * [new tag]               v3.9.2       -> v3.9.2
 * [new tag]               v3.9.2rc1    -> v3.9.2rc1
 * [new tag]               v3.9.3       -> v3.9.3
 * [new tag]               v3.9.4       -> v3.9.4
 * [new tag]               v3.9.5       -> v3.9.5
 * [new tag]               v3.9.6       -> v3.9.6
 * [new tag]               v3.9.7       -> v3.9.7
 * [new tag]               v3.9.8       -> v3.9.8
 * [new tag]               v3.9.9       -> v3.9.9
git fetch origin --depth 50 --force --tags --prune --prune-tags main  38,58s user 3,97s system 46% cpu 1:31,34 total

A little extra experiment

We can cut off almost the entire 1½ minute from the fetch command by just fetching 1 commit and no tags. I think the problem is that --depth 50 + --tags = "get 50 commits for each tag".

Total time: 0.7s

Details

time git fetch origin --depth 1 --force --prune --prune-tags main                     
remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
From https://github.com/python/cpython
 * branch            main       -> FETCH_HEAD
git fetch origin --depth 1 --force --prune --prune-tags main  0,05s user 0,02s system 10% cpu 0,710 total

I get this assumption confirmed by running the command with --depth 1 and -tags, now we slice off a bunch of seconds because we aren't getting additional commits.

git fetch origin --depth 1 --force --prune --prune-tags --tags main

Total time: 76.5s

Details

time git fetch origin --depth 1 --force --prune --prune-tags --tags main                               
remote: Enumerating objects: 152053, done.
remote: Counting objects: 100% (152053/152053), done.
remote: Compressing objects: 100% (65225/65225), done.
remote: Total 148676 (delta 126720), reused 100730 (delta 82160), pack-reused 0
Receiving objects: 100% (148676/148676), 198.49 MiB | 9.17 MiB/s, done.
Resolving deltas: 100% (126720/126720), completed with 2846 local objects.
From https://github.com/python/cpython
 * branch                main         -> FETCH_HEAD
 * [new tag]             2.0          -> 2.0
 * [new tag]             2.1          -> 2.1
 * [new tag]             2.2          -> 2.2
 * [new tag]             2.3          -> 2.3
 * [new tag]             2.4          -> 2.4
 * [new tag]             2.5          -> 2.5
 * [new tag]             2.6          -> 2.6
 * [new tag]             2.7          -> 2.7
 * [new tag]             3.0          -> 3.0
 * [new tag]             3.1          -> 3.1
 * [new tag]             3.2          -> 3.2
 * [new tag]             3.3          -> 3.3
 * [new tag]             3.4          -> 3.4
 * [new tag]             3.5          -> 3.5
 * [new tag]             3.6          -> 3.6
 * [new tag]             legacy-trunk -> legacy-trunk
 * [new tag]             v0.9.8       -> v0.9.8
 * [new tag]             v0.9.9       -> v0.9.9
 * [new tag]             v1.0.1       -> v1.0.1
 * [new tag]             v1.0.2       -> v1.0.2
 * [new tag]             v1.1         -> v1.1
 * [new tag]             v1.1.1       -> v1.1.1
 * [new tag]             v1.2         -> v1.2
 * [new tag]             v1.2b1       -> v1.2b1
 * [new tag]             v1.2b2       -> v1.2b2
 * [new tag]             v1.2b3       -> v1.2b3
 * [new tag]             v1.2b4       -> v1.2b4
 * [new tag]             v1.3         -> v1.3
 * [new tag]             v1.3b1       -> v1.3b1
 * [new tag]             v1.4         -> v1.4
 * [new tag]             v1.4b1       -> v1.4b1
 * [new tag]             v1.4b2       -> v1.4b2
 * [new tag]             v1.4b3       -> v1.4b3
 * [new tag]             v1.5         -> v1.5
 * [new tag]             v1.5.1       -> v1.5.1
 * [new tag]             v1.5.2       -> v1.5.2
 * [new tag]             v1.5.2a1     -> v1.5.2a1
 * [new tag]             v1.5.2a2     -> v1.5.2a2
 * [new tag]             v1.5.2b1     -> v1.5.2b1
 * [new tag]             v1.5.2b2     -> v1.5.2b2
 * [new tag]             v1.5.2c1     -> v1.5.2c1
 * [new tag]             v1.5a1       -> v1.5a1
 * [new tag]             v1.5a2       -> v1.5a2
 * [new tag]             v1.5a3       -> v1.5a3
 * [new tag]             v1.5a4       -> v1.5a4
 * [new tag]             v1.5b1       -> v1.5b1
 * [new tag]             v1.5b2       -> v1.5b2
 * [new tag]             v1.6a1       -> v1.6a1
 * [new tag]             v1.6a2       -> v1.6a2
 * [new tag]             v2.0         -> v2.0
 * [new tag]             v2.0.1       -> v2.0.1
 * [new tag]             v2.0.1c1     -> v2.0.1c1
 * [new tag]             v2.0b1       -> v2.0b1
 * [new tag]             v2.0b2       -> v2.0b2
 * [new tag]             v2.0c1       -> v2.0c1
 * [new tag]             v2.1         -> v2.1
 * [new tag]             v2.1.1       -> v2.1.1
 * [new tag]             v2.1.1c1     -> v2.1.1c1
 * [new tag]             v2.1.2       -> v2.1.2
 * [new tag]             v2.1.2c1     -> v2.1.2c1
 * [new tag]             v2.1.3       -> v2.1.3
 * [new tag]             v2.1a1       -> v2.1a1
 * [new tag]             v2.1a2       -> v2.1a2
 * [new tag]             v2.1b1       -> v2.1b1
 * [new tag]             v2.1b2       -> v2.1b2
 * [new tag]             v2.1c1       -> v2.1c1
 * [new tag]             v2.1c2       -> v2.1c2
 * [new tag]             v2.2         -> v2.2
 * [new tag]             v2.2.1       -> v2.2.1
 * [new tag]             v2.2.1c1     -> v2.2.1c1
 * [new tag]             v2.2.1c2     -> v2.2.1c2
 * [new tag]             v2.2.2       -> v2.2.2
 * [new tag]             v2.2.2b1     -> v2.2.2b1
 * [new tag]             v2.2.3       -> v2.2.3
 * [new tag]             v2.2.3c1     -> v2.2.3c1
 * [new tag]             v2.2a3       -> v2.2a3
 * [new tag]             v2.3.1       -> v2.3.1
 * [new tag]             v2.3.2       -> v2.3.2
 * [new tag]             v2.3.2c1     -> v2.3.2c1
 * [new tag]             v2.3.3       -> v2.3.3
 * [new tag]             v2.3.3c1     -> v2.3.3c1
 * [new tag]             v2.3.4       -> v2.3.4
 * [new tag]             v2.3.4c1     -> v2.3.4c1
 * [new tag]             v2.3.5       -> v2.3.5
 * [new tag]             v2.3.5c1     -> v2.3.5c1
 * [new tag]             v2.3.6       -> v2.3.6
 * [new tag]             v2.3.6c1     -> v2.3.6c1
 * [new tag]             v2.3.7       -> v2.3.7
 * [new tag]             v2.3.7c1     -> v2.3.7c1
 * [new tag]             v2.3c1       -> v2.3c1
 * [new tag]             v2.3c2       -> v2.3c2
 * [new tag]             v2.4         -> v2.4
 * [new tag]             v2.4.1       -> v2.4.1
 * [new tag]             v2.4.1c1     -> v2.4.1c1
 * [new tag]             v2.4.1c2     -> v2.4.1c2
 * [new tag]             v2.4.2       -> v2.4.2
 * [new tag]             v2.4.2c1     -> v2.4.2c1
 * [new tag]             v2.4.3       -> v2.4.3
 * [new tag]             v2.4.3c1     -> v2.4.3c1
 * [new tag]             v2.4.4       -> v2.4.4
 * [new tag]             v2.4.4c1     -> v2.4.4c1
 * [new tag]             v2.4.5       -> v2.4.5
 * [new tag]             v2.4.5c1     -> v2.4.5c1
 * [new tag]             v2.4.6       -> v2.4.6
 * [new tag]             v2.4.6c1     -> v2.4.6c1
 * [new tag]             v2.4a1       -> v2.4a1
 * [new tag]             v2.4a2       -> v2.4a2
 * [new tag]             v2.4a3       -> v2.4a3
 * [new tag]             v2.4b1       -> v2.4b1
 * [new tag]             v2.4b2       -> v2.4b2
 * [new tag]             v2.4c1       -> v2.4c1
 * [new tag]             v2.5         -> v2.5
 * [new tag]             v2.5.1       -> v2.5.1
 * [new tag]             v2.5.1c1     -> v2.5.1c1
 * [new tag]             v2.5.2       -> v2.5.2
 * [new tag]             v2.5.2c1     -> v2.5.2c1
 * [new tag]             v2.5.3       -> v2.5.3
 * [new tag]             v2.5.3c1     -> v2.5.3c1
 * [new tag]             v2.5.4       -> v2.5.4
 * [new tag]             v2.5.5       -> v2.5.5
 * [new tag]             v2.5.5c1     -> v2.5.5c1
 * [new tag]             v2.5.5c2     -> v2.5.5c2
 * [new tag]             v2.5.6       -> v2.5.6
 * [new tag]             v2.5.6c1     -> v2.5.6c1
 * [new tag]             v2.5a0       -> v2.5a0
 * [new tag]             v2.5a1       -> v2.5a1
 * [new tag]             v2.5a2       -> v2.5a2
 * [new tag]             v2.5b1       -> v2.5b1
 * [new tag]             v2.5b2       -> v2.5b2
 * [new tag]             v2.5b3       -> v2.5b3
 * [new tag]             v2.5c1       -> v2.5c1
 * [new tag]             v2.5c2       -> v2.5c2
 * [new tag]             v2.6         -> v2.6
 * [new tag]             v2.6.1       -> v2.6.1
 * [new tag]             v2.6.2       -> v2.6.2
 * [new tag]             v2.6.2c1     -> v2.6.2c1
 * [new tag]             v2.6.3       -> v2.6.3
 * [new tag]             v2.6.3rc1    -> v2.6.3rc1
 * [new tag]             v2.6.4       -> v2.6.4
 * [new tag]             v2.6.4rc1    -> v2.6.4rc1
 * [new tag]             v2.6.4rc2    -> v2.6.4rc2
 * [new tag]             v2.6.5       -> v2.6.5
 * [new tag]             v2.6.5rc1    -> v2.6.5rc1
 * [new tag]             v2.6.5rc2    -> v2.6.5rc2
 * [new tag]             v2.6.6       -> v2.6.6
 * [new tag]             v2.6.6rc1    -> v2.6.6rc1
 * [new tag]             v2.6.6rc2    -> v2.6.6rc2
 * [new tag]             v2.6.7       -> v2.6.7
 * [new tag]             v2.6.8       -> v2.6.8
 * [new tag]             v2.6.8rc1    -> v2.6.8rc1
 * [new tag]             v2.6.8rc2    -> v2.6.8rc2
 * [new tag]             v2.6.9       -> v2.6.9
 * [new tag]             v2.6.9rc1    -> v2.6.9rc1
 * [new tag]             v2.6a1       -> v2.6a1
 * [new tag]             v2.6a2       -> v2.6a2
 * [new tag]             v2.6a3       -> v2.6a3
 * [new tag]             v2.6b1       -> v2.6b1
 * [new tag]             v2.6b2       -> v2.6b2
 * [new tag]             v2.6b3       -> v2.6b3
 * [new tag]             v2.6rc1      -> v2.6rc1
 * [new tag]             v2.6rc2      -> v2.6rc2
 * [new tag]             v2.7         -> v2.7
 * [new tag]             v2.7.1       -> v2.7.1
 * [new tag]             v2.7.10      -> v2.7.10
 * [new tag]             v2.7.10rc1   -> v2.7.10rc1
 * [new tag]             v2.7.11      -> v2.7.11
 * [new tag]             v2.7.11rc1   -> v2.7.11rc1
 * [new tag]             v2.7.12      -> v2.7.12
 * [new tag]             v2.7.12rc1   -> v2.7.12rc1
 * [new tag]             v2.7.13      -> v2.7.13
 * [new tag]             v2.7.13rc1   -> v2.7.13rc1
 * [new tag]             v2.7.14      -> v2.7.14
 * [new tag]             v2.7.14rc1   -> v2.7.14rc1
 * [new tag]             v2.7.15      -> v2.7.15
 * [new tag]             v2.7.15rc1   -> v2.7.15rc1
 * [new tag]             v2.7.16      -> v2.7.16
 * [new tag]             v2.7.16rc1   -> v2.7.16rc1
 * [new tag]             v2.7.17      -> v2.7.17
 * [new tag]             v2.7.17rc1   -> v2.7.17rc1
 * [new tag]             v2.7.18      -> v2.7.18
 * [new tag]             v2.7.18rc1   -> v2.7.18rc1
 * [new tag]             v2.7.1rc1    -> v2.7.1rc1
 * [new tag]             v2.7.2       -> v2.7.2
 * [new tag]             v2.7.2rc1    -> v2.7.2rc1
 * [new tag]             v2.7.3       -> v2.7.3
 * [new tag]             v2.7.3rc1    -> v2.7.3rc1
 * [new tag]             v2.7.3rc2    -> v2.7.3rc2
 * [new tag]             v2.7.4       -> v2.7.4
 * [new tag]             v2.7.4rc1    -> v2.7.4rc1
 * [new tag]             v2.7.5       -> v2.7.5
 * [new tag]             v2.7.6       -> v2.7.6
 * [new tag]             v2.7.6rc1    -> v2.7.6rc1
 * [new tag]             v2.7.7       -> v2.7.7
 * [new tag]             v2.7.7rc1    -> v2.7.7rc1
 * [new tag]             v2.7.8       -> v2.7.8
 * [new tag]             v2.7.9       -> v2.7.9
 * [new tag]             v2.7.9rc1    -> v2.7.9rc1
 * [new tag]             v2.7a1       -> v2.7a1
 * [new tag]             v2.7a2       -> v2.7a2
 * [new tag]             v2.7a3       -> v2.7a3
 * [new tag]             v2.7a4       -> v2.7a4
 * [new tag]             v2.7b1       -> v2.7b1
 * [new tag]             v2.7b2       -> v2.7b2
 * [new tag]             v2.7rc1      -> v2.7rc1
 * [new tag]             v2.7rc2      -> v2.7rc2
 * [new tag]             v3.0         -> v3.0
 * [new tag]             v3.0.1       -> v3.0.1
 * [new tag]             v3.0a1       -> v3.0a1
 * [new tag]             v3.0a2       -> v3.0a2
 * [new tag]             v3.0a3       -> v3.0a3
 * [new tag]             v3.0a4       -> v3.0a4
 * [new tag]             v3.0a5       -> v3.0a5
 * [new tag]             v3.0b1       -> v3.0b1
 * [new tag]             v3.0b2       -> v3.0b2
 * [new tag]             v3.0b3       -> v3.0b3
 * [new tag]             v3.0rc1      -> v3.0rc1
 * [new tag]             v3.0rc2      -> v3.0rc2
 * [new tag]             v3.0rc3      -> v3.0rc3
 * [new tag]             v3.1         -> v3.1
 * [new tag]             v3.1.1       -> v3.1.1
 * [new tag]             v3.1.1rc1    -> v3.1.1rc1
 * [new tag]             v3.1.2       -> v3.1.2
 * [new tag]             v3.1.2rc1    -> v3.1.2rc1
 * [new tag]             v3.1.3       -> v3.1.3
 * [new tag]             v3.1.3rc1    -> v3.1.3rc1
 * [new tag]             v3.1.4       -> v3.1.4
 * [new tag]             v3.1.4rc1    -> v3.1.4rc1
 * [new tag]             v3.1.5       -> v3.1.5
 * [new tag]             v3.1.5rc1    -> v3.1.5rc1
 * [new tag]             v3.1.5rc2    -> v3.1.5rc2
 * [new tag]             v3.10.0      -> v3.10.0
 * [new tag]             v3.10.0a1    -> v3.10.0a1
 * [new tag]             v3.10.0a2    -> v3.10.0a2
 * [new tag]             v3.10.0a3    -> v3.10.0a3
 * [new tag]             v3.10.0a4    -> v3.10.0a4
 * [new tag]             v3.10.0a5    -> v3.10.0a5
 * [new tag]             v3.10.0a6    -> v3.10.0a6
 * [new tag]             v3.10.0a7    -> v3.10.0a7
 * [new tag]             v3.10.0b1    -> v3.10.0b1
 * [new tag]             v3.10.0b2    -> v3.10.0b2
 * [new tag]             v3.10.0b3    -> v3.10.0b3
 * [new tag]             v3.10.0b4    -> v3.10.0b4
 * [new tag]             v3.10.0rc1   -> v3.10.0rc1
 * [new tag]             v3.10.0rc2   -> v3.10.0rc2
 * [new tag]             v3.10.1      -> v3.10.1
 * [new tag]             v3.10.10     -> v3.10.10
 * [new tag]             v3.10.11     -> v3.10.11
 * [new tag]             v3.10.12     -> v3.10.12
 * [new tag]             v3.10.2      -> v3.10.2
 * [new tag]             v3.10.3      -> v3.10.3
 * [new tag]             v3.10.4      -> v3.10.4
 * [new tag]             v3.10.5      -> v3.10.5
 * [new tag]             v3.10.6      -> v3.10.6
 * [new tag]             v3.10.7      -> v3.10.7
 * [new tag]             v3.10.8      -> v3.10.8
 * [new tag]             v3.10.9      -> v3.10.9
 * [new tag]             v3.11.0      -> v3.11.0
 * [new tag]             v3.11.0a1    -> v3.11.0a1
 * [new tag]             v3.11.0a2    -> v3.11.0a2
 * [new tag]             v3.11.0a3    -> v3.11.0a3
 * [new tag]             v3.11.0a4    -> v3.11.0a4
 * [new tag]             v3.11.0a5    -> v3.11.0a5
 * [new tag]             v3.11.0a6    -> v3.11.0a6
 * [new tag]             v3.11.0a7    -> v3.11.0a7
 * [new tag]             v3.11.0b1    -> v3.11.0b1
 * [new tag]             v3.11.0b2    -> v3.11.0b2
 * [new tag]             v3.11.0b3    -> v3.11.0b3
 * [new tag]             v3.11.0b4    -> v3.11.0b4
 * [new tag]             v3.11.0b5    -> v3.11.0b5
 * [new tag]             v3.11.0rc1   -> v3.11.0rc1
 * [new tag]             v3.11.0rc2   -> v3.11.0rc2
 * [new tag]             v3.11.1      -> v3.11.1
 * [new tag]             v3.11.2      -> v3.11.2
 * [new tag]             v3.11.3      -> v3.11.3
 * [new tag]             v3.11.4      -> v3.11.4
 * [new tag]             v3.12.0a1    -> v3.12.0a1
 * [new tag]             v3.12.0a2    -> v3.12.0a2
 * [new tag]             v3.12.0a3    -> v3.12.0a3
 * [new tag]             v3.12.0a4    -> v3.12.0a4
 * [new tag]             v3.12.0a5    -> v3.12.0a5
 * [new tag]             v3.12.0a6    -> v3.12.0a6
 * [new tag]             v3.12.0a7    -> v3.12.0a7
 * [new tag]             v3.12.0b1    -> v3.12.0b1
 * [new tag]             v3.12.0b2    -> v3.12.0b2
 * [new tag]             v3.1a1       -> v3.1a1
 * [new tag]             v3.1a2       -> v3.1a2
 * [new tag]             v3.1b1       -> v3.1b1
 * [new tag]             v3.1rc1      -> v3.1rc1
 * [new tag]             v3.1rc2      -> v3.1rc2
 * [new tag]             v3.2         -> v3.2
 * [new tag]             v3.2.1       -> v3.2.1
 * [new tag]             v3.2.1b1     -> v3.2.1b1
 * [new tag]             v3.2.1rc1    -> v3.2.1rc1
 * [new tag]             v3.2.1rc2    -> v3.2.1rc2
 * [new tag]             v3.2.2       -> v3.2.2
 * [new tag]             v3.2.2rc1    -> v3.2.2rc1
 * [new tag]             v3.2.3       -> v3.2.3
 * [new tag]             v3.2.3rc1    -> v3.2.3rc1
 * [new tag]             v3.2.3rc2    -> v3.2.3rc2
 * [new tag]             v3.2.4       -> v3.2.4
 * [new tag]             v3.2.4rc1    -> v3.2.4rc1
 * [new tag]             v3.2.5       -> v3.2.5
 * [new tag]             v3.2.6       -> v3.2.6
 * [new tag]             v3.2.6rc1    -> v3.2.6rc1
 * [new tag]             v3.2a1       -> v3.2a1
 * [new tag]             v3.2a2       -> v3.2a2
 * [new tag]             v3.2a3       -> v3.2a3
 * [new tag]             v3.2a4       -> v3.2a4
 * [new tag]             v3.2b1       -> v3.2b1
 * [new tag]             v3.2b2       -> v3.2b2
 * [new tag]             v3.2rc1      -> v3.2rc1
 * [new tag]             v3.2rc2      -> v3.2rc2
 * [new tag]             v3.2rc3      -> v3.2rc3
 * [new tag]             v3.3.0       -> v3.3.0
 * [new tag]             v3.3.0a1     -> v3.3.0a1
 * [new tag]             v3.3.0a2     -> v3.3.0a2
 * [new tag]             v3.3.0a3     -> v3.3.0a3
 * [new tag]             v3.3.0a4     -> v3.3.0a4
 * [new tag]             v3.3.0b1     -> v3.3.0b1
 * [new tag]             v3.3.0b2     -> v3.3.0b2
 * [new tag]             v3.3.0rc1    -> v3.3.0rc1
 * [new tag]             v3.3.0rc2    -> v3.3.0rc2
 * [new tag]             v3.3.0rc3    -> v3.3.0rc3
 * [new tag]             v3.3.1       -> v3.3.1
 * [new tag]             v3.3.1rc1    -> v3.3.1rc1
 * [new tag]             v3.3.2       -> v3.3.2
 * [new tag]             v3.3.3       -> v3.3.3
 * [new tag]             v3.3.3rc1    -> v3.3.3rc1
 * [new tag]             v3.3.3rc2    -> v3.3.3rc2
 * [new tag]             v3.3.4       -> v3.3.4
 * [new tag]             v3.3.4rc1    -> v3.3.4rc1
 * [new tag]             v3.3.5       -> v3.3.5
 * [new tag]             v3.3.5rc1    -> v3.3.5rc1
 * [new tag]             v3.3.5rc2    -> v3.3.5rc2
 * [new tag]             v3.3.6       -> v3.3.6
 * [new tag]             v3.3.6rc1    -> v3.3.6rc1
 * [new tag]             v3.3.7       -> v3.3.7
 * [new tag]             v3.3.7rc1    -> v3.3.7rc1
 * [new tag]             v3.4.0       -> v3.4.0
 * [new tag]             v3.4.0a1     -> v3.4.0a1
 * [new tag]             v3.4.0a2     -> v3.4.0a2
 * [new tag]             v3.4.0a3     -> v3.4.0a3
 * [new tag]             v3.4.0a4     -> v3.4.0a4
 * [new tag]             v3.4.0b1     -> v3.4.0b1
 * [new tag]             v3.4.0b2     -> v3.4.0b2
 * [new tag]             v3.4.0b3     -> v3.4.0b3
 * [new tag]             v3.4.0rc1    -> v3.4.0rc1
 * [new tag]             v3.4.0rc2    -> v3.4.0rc2
 * [new tag]             v3.4.0rc3    -> v3.4.0rc3
 * [new tag]             v3.4.1       -> v3.4.1
 * [new tag]             v3.4.10      -> v3.4.10
 * [new tag]             v3.4.10rc1   -> v3.4.10rc1
 * [new tag]             v3.4.1rc1    -> v3.4.1rc1
 * [new tag]             v3.4.2       -> v3.4.2
 * [new tag]             v3.4.2rc1    -> v3.4.2rc1
 * [new tag]             v3.4.3       -> v3.4.3
 * [new tag]             v3.4.3rc1    -> v3.4.3rc1
 * [new tag]             v3.4.4       -> v3.4.4
 * [new tag]             v3.4.4rc1    -> v3.4.4rc1
 * [new tag]             v3.4.5       -> v3.4.5
 * [new tag]             v3.4.5rc1    -> v3.4.5rc1
 * [new tag]             v3.4.6       -> v3.4.6
 * [new tag]             v3.4.6rc1    -> v3.4.6rc1
 * [new tag]             v3.4.7       -> v3.4.7
 * [new tag]             v3.4.7rc1    -> v3.4.7rc1
 * [new tag]             v3.4.8       -> v3.4.8
 * [new tag]             v3.4.8rc1    -> v3.4.8rc1
 * [new tag]             v3.4.9       -> v3.4.9
 * [new tag]             v3.4.9rc1    -> v3.4.9rc1
 * [new tag]             v3.5.0       -> v3.5.0
 * [new tag]             v3.5.0a1     -> v3.5.0a1
 * [new tag]             v3.5.0a2     -> v3.5.0a2
 * [new tag]             v3.5.0a3     -> v3.5.0a3
 * [new tag]             v3.5.0a4     -> v3.5.0a4
 * [new tag]             v3.5.0b1     -> v3.5.0b1
 * [new tag]             v3.5.0b2     -> v3.5.0b2
 * [new tag]             v3.5.0b3     -> v3.5.0b3
 * [new tag]             v3.5.0b4     -> v3.5.0b4
 * [new tag]             v3.5.0rc1    -> v3.5.0rc1
 * [new tag]             v3.5.0rc2    -> v3.5.0rc2
 * [new tag]             v3.5.0rc3    -> v3.5.0rc3
 * [new tag]             v3.5.0rc4    -> v3.5.0rc4
 * [new tag]             v3.5.1       -> v3.5.1
 * [new tag]             v3.5.10      -> v3.5.10
 * [new tag]             v3.5.10rc1   -> v3.5.10rc1
 * [new tag]             v3.5.1rc1    -> v3.5.1rc1
 * [new tag]             v3.5.2       -> v3.5.2
 * [new tag]             v3.5.2rc1    -> v3.5.2rc1
 * [new tag]             v3.5.3       -> v3.5.3
 * [new tag]             v3.5.3rc1    -> v3.5.3rc1
 * [new tag]             v3.5.4       -> v3.5.4
 * [new tag]             v3.5.4rc1    -> v3.5.4rc1
 * [new tag]             v3.5.5       -> v3.5.5
 * [new tag]             v3.5.5rc1    -> v3.5.5rc1
 * [new tag]             v3.5.6       -> v3.5.6
 * [new tag]             v3.5.6rc1    -> v3.5.6rc1
 * [new tag]             v3.5.7       -> v3.5.7
 * [new tag]             v3.5.7rc1    -> v3.5.7rc1
 * [new tag]             v3.5.8       -> v3.5.8
 * [new tag]             v3.5.8rc1    -> v3.5.8rc1
 * [new tag]             v3.5.8rc2    -> v3.5.8rc2
 * [new tag]             v3.5.9       -> v3.5.9
 * [new tag]             v3.6.0       -> v3.6.0
 * [new tag]             v3.6.0a1     -> v3.6.0a1
 * [new tag]             v3.6.0a2     -> v3.6.0a2
 * [new tag]             v3.6.0a3     -> v3.6.0a3
 * [new tag]             v3.6.0a4     -> v3.6.0a4
 * [new tag]             v3.6.0b1     -> v3.6.0b1
 * [new tag]             v3.6.0b2     -> v3.6.0b2
 * [new tag]             v3.6.0b3     -> v3.6.0b3
 * [new tag]             v3.6.0b4     -> v3.6.0b4
 * [new tag]             v3.6.0rc1    -> v3.6.0rc1
 * [new tag]             v3.6.0rc2    -> v3.6.0rc2
 * [new tag]             v3.6.1       -> v3.6.1
 * [new tag]             v3.6.10      -> v3.6.10
 * [new tag]             v3.6.10rc1   -> v3.6.10rc1
 * [new tag]             v3.6.11      -> v3.6.11
 * [new tag]             v3.6.11rc1   -> v3.6.11rc1
 * [new tag]             v3.6.12      -> v3.6.12
 * [new tag]             v3.6.13      -> v3.6.13
 * [new tag]             v3.6.14      -> v3.6.14
 * [new tag]             v3.6.15      -> v3.6.15
 * [new tag]             v3.6.1rc1    -> v3.6.1rc1
 * [new tag]             v3.6.2       -> v3.6.2
 * [new tag]             v3.6.2rc1    -> v3.6.2rc1
 * [new tag]             v3.6.2rc2    -> v3.6.2rc2
 * [new tag]             v3.6.3       -> v3.6.3
 * [new tag]             v3.6.3rc1    -> v3.6.3rc1
 * [new tag]             v3.6.4       -> v3.6.4
 * [new tag]             v3.6.4rc1    -> v3.6.4rc1
 * [new tag]             v3.6.5       -> v3.6.5
 * [new tag]             v3.6.5rc1    -> v3.6.5rc1
 * [new tag]             v3.6.6       -> v3.6.6
 * [new tag]             v3.6.6rc1    -> v3.6.6rc1
 * [new tag]             v3.6.7       -> v3.6.7
 * [new tag]             v3.6.7rc1    -> v3.6.7rc1
 * [new tag]             v3.6.7rc2    -> v3.6.7rc2
 * [new tag]             v3.6.8       -> v3.6.8
 * [new tag]             v3.6.8rc1    -> v3.6.8rc1
 * [new tag]             v3.6.9       -> v3.6.9
 * [new tag]             v3.6.9rc1    -> v3.6.9rc1
 * [new tag]             v3.7.0       -> v3.7.0
 * [new tag]             v3.7.0a1     -> v3.7.0a1
 * [new tag]             v3.7.0a2     -> v3.7.0a2
 * [new tag]             v3.7.0a3     -> v3.7.0a3
 * [new tag]             v3.7.0a4     -> v3.7.0a4
 * [new tag]             v3.7.0b1     -> v3.7.0b1
 * [new tag]             v3.7.0b2     -> v3.7.0b2
 * [new tag]             v3.7.0b3     -> v3.7.0b3
 * [new tag]             v3.7.0b4     -> v3.7.0b4
 * [new tag]             v3.7.0b5     -> v3.7.0b5
 * [new tag]             v3.7.0rc1    -> v3.7.0rc1
 * [new tag]             v3.7.1       -> v3.7.1
 * [new tag]             v3.7.10      -> v3.7.10
 * [new tag]             v3.7.11      -> v3.7.11
 * [new tag]             v3.7.12      -> v3.7.12
 * [new tag]             v3.7.13      -> v3.7.13
 * [new tag]             v3.7.14      -> v3.7.14
 * [new tag]             v3.7.15      -> v3.7.15
 * [new tag]             v3.7.16      -> v3.7.16
 * [new tag]             v3.7.17      -> v3.7.17
 * [new tag]             v3.7.1rc1    -> v3.7.1rc1
 * [new tag]             v3.7.1rc2    -> v3.7.1rc2
 * [new tag]             v3.7.2       -> v3.7.2
 * [new tag]             v3.7.2rc1    -> v3.7.2rc1
 * [new tag]             v3.7.3       -> v3.7.3
 * [new tag]             v3.7.3rc1    -> v3.7.3rc1
 * [new tag]             v3.7.4       -> v3.7.4
 * [new tag]             v3.7.4rc1    -> v3.7.4rc1
 * [new tag]             v3.7.4rc2    -> v3.7.4rc2
 * [new tag]             v3.7.5       -> v3.7.5
 * [new tag]             v3.7.5rc1    -> v3.7.5rc1
 * [new tag]             v3.7.6       -> v3.7.6
 * [new tag]             v3.7.6rc1    -> v3.7.6rc1
 * [new tag]             v3.7.7       -> v3.7.7
 * [new tag]             v3.7.7rc1    -> v3.7.7rc1
 * [new tag]             v3.7.8       -> v3.7.8
 * [new tag]             v3.7.8rc1    -> v3.7.8rc1
 * [new tag]             v3.7.9       -> v3.7.9
 * [new tag]             v3.8.0       -> v3.8.0
 * [new tag]             v3.8.0a1     -> v3.8.0a1
 * [new tag]             v3.8.0a2     -> v3.8.0a2
 * [new tag]             v3.8.0a3     -> v3.8.0a3
 * [new tag]             v3.8.0a4     -> v3.8.0a4
 * [new tag]             v3.8.0b1     -> v3.8.0b1
 * [new tag]             v3.8.0b2     -> v3.8.0b2
 * [new tag]             v3.8.0b3     -> v3.8.0b3
 * [new tag]             v3.8.0b4     -> v3.8.0b4
 * [new tag]             v3.8.0rc1    -> v3.8.0rc1
 * [new tag]             v3.8.1       -> v3.8.1
 * [new tag]             v3.8.10      -> v3.8.10
 * [new tag]             v3.8.11      -> v3.8.11
 * [new tag]             v3.8.12      -> v3.8.12
 * [new tag]             v3.8.13      -> v3.8.13
 * [new tag]             v3.8.14      -> v3.8.14
 * [new tag]             v3.8.15      -> v3.8.15
 * [new tag]             v3.8.16      -> v3.8.16
 * [new tag]             v3.8.17      -> v3.8.17
 * [new tag]             v3.8.1rc1    -> v3.8.1rc1
 * [new tag]             v3.8.2       -> v3.8.2
 * [new tag]             v3.8.2rc1    -> v3.8.2rc1
 * [new tag]             v3.8.2rc2    -> v3.8.2rc2
 * [new tag]             v3.8.3       -> v3.8.3
 * [new tag]             v3.8.3rc1    -> v3.8.3rc1
 * [new tag]             v3.8.4       -> v3.8.4
 * [new tag]             v3.8.4rc1    -> v3.8.4rc1
 * [new tag]             v3.8.5       -> v3.8.5
 * [new tag]             v3.8.6       -> v3.8.6
 * [new tag]             v3.8.6rc1    -> v3.8.6rc1
 * [new tag]             v3.8.7       -> v3.8.7
 * [new tag]             v3.8.7rc1    -> v3.8.7rc1
 * [new tag]             v3.8.8       -> v3.8.8
 * [new tag]             v3.8.8rc1    -> v3.8.8rc1
 * [new tag]             v3.8.9       -> v3.8.9
 * [new tag]             v3.9.0       -> v3.9.0
 * [new tag]             v3.9.0a1     -> v3.9.0a1
 * [new tag]             v3.9.0a2     -> v3.9.0a2
 * [new tag]             v3.9.0a3     -> v3.9.0a3
 * [new tag]             v3.9.0a4     -> v3.9.0a4
 * [new tag]             v3.9.0a5     -> v3.9.0a5
 * [new tag]             v3.9.0a6     -> v3.9.0a6
 * [new tag]             v3.9.0b1     -> v3.9.0b1
 * [new tag]             v3.9.0b2     -> v3.9.0b2
 * [new tag]             v3.9.0b3     -> v3.9.0b3
 * [new tag]             v3.9.0b4     -> v3.9.0b4
 * [new tag]             v3.9.0b5     -> v3.9.0b5
 * [new tag]             v3.9.0rc1    -> v3.9.0rc1
 * [new tag]             v3.9.0rc2    -> v3.9.0rc2
 * [new tag]             v3.9.1       -> v3.9.1
 * [new tag]             v3.9.10      -> v3.9.10
 * [new tag]             v3.9.11      -> v3.9.11
 * [new tag]             v3.9.12      -> v3.9.12
 * [new tag]             v3.9.13      -> v3.9.13
 * [new tag]             v3.9.14      -> v3.9.14
 * [new tag]             v3.9.15      -> v3.9.15
 * [new tag]             v3.9.16      -> v3.9.16
 * [new tag]             v3.9.17      -> v3.9.17
 * [new tag]             v3.9.1rc1    -> v3.9.1rc1
 * [new tag]             v3.9.2       -> v3.9.2
 * [new tag]             v3.9.2rc1    -> v3.9.2rc1
 * [new tag]             v3.9.3       -> v3.9.3
 * [new tag]             v3.9.4       -> v3.9.4
 * [new tag]             v3.9.5       -> v3.9.5
 * [new tag]             v3.9.6       -> v3.9.6
 * [new tag]             v3.9.7       -> v3.9.7
 * [new tag]             v3.9.8       -> v3.9.8
 * [new tag]             v3.9.9       -> v3.9.9
git fetch origin --depth 1 --force --prune --prune-tags --tags main  26,55s user 2,99s system 38% cpu 1:16,51 total

If we want to keep --depth 50, we could also speed up the command quite a lot by removing --tags.

This command means "get the main branch w/ 50 commits". Since we are specifying with remote reference, we also need to make it point to something locally.

git fetch origin --depth 50 --force --prune --prune-tags main

Total time: 1.2s

To make it work for a tag, we would have to do:

git fetch origin--depth 50 --force --prune --prune-tags refs/tags/1.0.0:refs/tags/1.0.0

This means "get a tag (no need to guess that it's a tag, we use the explicit refs/tags prefix) and create a matching local reference"

Details

time git fetch origin --depth 50 --force --prune --prune-tags main                       
remote: Enumerating objects: 700, done.
remote: Counting objects: 100% (700/700), done.
remote: Compressing objects: 100% (379/379), done.
remote: Total 519 (delta 464), reused 188 (delta 139), pack-reused 0
Receiving objects: 100% (519/519), 117.31 KiB | 4.04 MiB/s, done.
Resolving deltas: 100% (464/464), completed with 176 local objects.
From https://github.com/python/cpython
 * branch            main       -> FETCH_HEAD
git fetch origin --depth 50 --force --prune --prune-tags main  0,22s user 0,04s system 20% cpu 1,276 total

Next step?

With the current changes and scope of work in mind, I would also go ahead and remove --tags from the fetch command. I'm leaning towards slicing off the additional 1½ minute from git fetch by removing --tags, now that we are already doing all the work to test and verify.

@humitos what's your thoughts on this? I think that comparing it to all the other changes, it's such a small adjustment with a big effect.

Copy link
Member

@humitos humitos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the current changes and scope of work in mind, I would also go ahead and remove --tags from the fetch command. I'm leaning towards slicing off the additional 1½ minute from git fetch by removing --tags, now that we are already doing all the work to test and verify.
@humitos what's your thoughts on this? I think that comparing it to all the other changes, it's such a small adjustment with a big effect.

Sounds good to me. To summarize, can you write here what are going to be the commands for each case? I understand that the set of commands will be exactly the same for all the cases, with the only difference being the fetched reference (at the end of the command)

  • on branches: {verbose_name}
  • on tags: refs/tags/{verbose_name}:refs/tags/{verbose_name}
  • on PRs: pull/{verbose_name}/head:external-{verbose_name}

Then, the set of commands would be:

git clone --depth 1 --no-checkout <repository url>
git fetch origin --depth 50 <reference generated by RTD>
git checkout <verbose_name>

If I am correct here, let's move forward with this approach. Then we can slowly roll this out and check if there are projects affected by this and fix those edge cases.

common Outdated Show resolved Hide resolved
readthedocs/builds/tasks.py Outdated Show resolved Hide resolved
readthedocs/doc_builder/director.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/bzr.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/hg.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
@humitos
Copy link
Member

humitos commented Jun 14, 2023

There is one more thing that you will need to think about. The case when there is no identifier and we have to default to "default branch of the repository". This case was originally introduced at #9424

@benjaoming
Copy link
Contributor Author

There is one more thing that you will need to think about. The case when there is no identifier and we have to default to "default branch of the repository".

That's why the identifier is optional for the fetch command. I can definitely check the behavior for projects without default branches 👍

Copy link
Contributor Author

@benjaoming benjaoming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding some comments and questions about various decisions. If you see anything you would like as an inline comment, LMK 👍

Feel free to resolve!

readthedocs/api/v2/serializers.py Outdated Show resolved Hide resolved
readthedocs/projects/tasks/mixins.py Outdated Show resolved Hide resolved
readthedocs/rtd_tests/tests/test_backend.py Outdated Show resolved Hide resolved
readthedocs/rtd_tests/tests/test_backend.py Outdated Show resolved Hide resolved
readthedocs/rtd_tests/tests/test_backend.py Outdated Show resolved Hide resolved
{branch.verbose_name for branch in repo.branches},
)

def test_update_without_branch_name(self):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is new

readthedocs/rtd_tests/tests/test_backend.py Show resolved Hide resolved
@benjaoming benjaoming marked this pull request as ready for review June 20, 2023 17:11
Copy link
Member

@humitos humitos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going in a good direction 👍🏼

I have some suggestions and opinions here about the implementation, code style, naming and others. I wrote some comments and questions that I'd like you to address before merging.

Besides, I'm pinging @stsewd to jump into the review of this code as well because it touches the build system, which is not trivial and it's easy to miss some use cases, and edge ones. The code itself it's not complex, but the context is. So, better to have more eyes here.

readthedocs/api/v2/serializers.py Outdated Show resolved Hide resolved
readthedocs/doc_builder/director.py Show resolved Hide resolved
readthedocs/projects/models.py Outdated Show resolved Hide resolved
readthedocs/projects/tasks/mixins.py Outdated Show resolved Hide resolved
readthedocs/projects/tasks/mixins.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Outdated Show resolved Hide resolved
Co-authored-by: Manuel Kaufmann <humitos@gmail.com>
@jcfr
Copy link

jcfr commented Jun 22, 2023

Once this is integrated, I will rebase:

Copy link
Member

@stsewd stsewd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some comments around not breaking other VCSs backends. There are a lot of previous conversations I didn't take a look at, let me know if there are any relevant ones that my need my input.

readthedocs/projects/tasks/mixins.py Outdated Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Show resolved Hide resolved
readthedocs/vcs_support/backends/git.py Show resolved Hide resolved
@benjaoming
Copy link
Contributor Author

benjaoming commented Jun 27, 2023

Did a bunch of local Q&A with the latest main merged in and everything looked good, including building without the feature flag.

@humitos
Copy link
Member

humitos commented Jul 10, 2023

I did some local QA and I was able to build all the versions I tested from test-builds. Besides, I also tested the case for a new imported project and it worked fine. I'm merging this PR now since it shouldn't affect existing projects and we can start rolling it out slowly to new projects and some manually selected projects.

Thanks for this awesome work 💯! This feature was not an easy one 👍🏼

@humitos humitos enabled auto-merge (squash) July 10, 2023 12:23
@humitos humitos merged commit 1add44a into main Jul 10, 2023
7 checks passed
@humitos humitos deleted the feature/git-clone-fetch-checkout branch July 10, 2023 12:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Build: cloning multibranch repository takes too long
4 participants