cli: [Regression] Cannot create and clone repo from template repo

Describe the bug

This worked around 2.21 but has been broken since at least 2.22: running gh repo create {name} --template {template} --clone fails with error,

fatal: couldn’t find remote ref refs/heads/main failed to run git: exit status 128

It does create the repo from the template correctly and a local directory for the clone is created with a .git directory, but no content is checked out. If I go into the fetched repo and run, say, git pull --ff-only, no tracking branch is set.

This does not repro if you don’t specify a --template e.g., gh repo create {name} --clone.

Steps to reproduce the behavior

  1. Type this: gh repo create example --template heaths/template-rustlang --clone --public
  2. See error

Expected vs actual behavior

The repo should be created, cloned, and working directory checked out. This worked up until, IIRC, 2.21.

Logs

The following from setting GH_DEBUG="api" is abbreviated to show what seems relevant parts. There’s some look-ups at the beginning that don’t seem relevant, but can easily be reproduced:

* Request took 139.4075ms
* Request at 2023-02-27 16:07:38.9301338 -0800 PST m=+0.508462901
* Request to https://api.github.com/graphql
> POST /graphql HTTP/1.1
> Host: api.github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token XXXXXXXXXXXXXXXXXXXXXXXX
> Content-Length: 503
> Content-Type: application/json; charset=utf-8
> Graphql-Features: merge_queue
> Time-Zone: America/Los_Angeles
> User-Agent: GitHub CLI 2.23.0

GraphQL query:
mutation CloneTemplateRepository($input: CloneTemplateRepositoryInput!) {
      cloneTemplateRepository(input: $input) {
        repository {
          id
          name
          owner { login }
          url
        }
      }
    }
GraphQL variables: {"input":{"name":"autorest-diff4","visibility":"PUBLIC","description":"Compares OpenAPI specifications from different AutoRest tags","ownerId":"MDQ6VXNlcjE1MzI0ODY=","repositoryId":"R_kgDOIZk6lg","includeAllBranches":false}}

< HTTP/2.0 200 OK
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset
< Content-Security-Policy: default-src 'none'
< Content-Type: application/json; charset=utf-8
< Date: Tue, 28 Feb 2023 00:07:40 GMT
< Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
< Server: GitHub.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Vary: Accept-Encoding, Accept, X-Requested-With
< X-Accepted-Oauth-Scopes: repo
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Github-Media-Type: github.merge-info-preview; param=nebula-preview; format=json
< X-Github-Request-Id: CF7D:6F8D:B91DDC5:BEB30AC:63FD45CA
< X-Oauth-Client-Id: 178c6fc778ccc68e1d6a
< X-Oauth-Scopes: delete_repo, gist, project, read:org, read:packages, read:user, repo, workflow
< X-Ratelimit-Limit: 5000
< X-Ratelimit-Remaining: 4987
< X-Ratelimit-Reset: 1677545896
< X-Ratelimit-Resource: graphql
< X-Ratelimit-Used: 13
< X-Xss-Protection: 0

{
  "data": {
    "cloneTemplateRepository": {
      "repository": {
        "id": "R_kgDOJDSPuQ",
        "name": "autorest-diff4",
        "owner": {
          "login": "heaths"
        },
        "url": "https://github.com/heaths/autorest-diff4"
      }
    }
  },
  "extensions": {
    "warnings": [
      {
        "type": "DEPRECATION",
        "message": "The id MDQ6VXNlcjE1MzI0ODY= is deprecated. Update your cache to use the next_global_id from the data payload.",
        "data": {
          "legacy_global_id": "MDQ6VXNlcjE1MzI0ODY=",
          "next_global_id": "U_kgDOABdiRg"
        },
        "link": "https://docs.github.com"
      }
    ]
  }
}

* Request took 1.7720767s
[git.exe init autorest-diff4]
[git.exe -C autorest-diff4 remote add origin https://github.com/heaths/autorest-diff4.git]
[git.exe -C autorest-diff4 -c credential.helper= -c credential.helper=!"C:\\Program Files\\GitHub CLI\\gh.exe" auth git-credential fetch origin +refs/heads/main:refs/remotes/origin/main]
fatal: couldn't find remote ref refs/heads/main
failed to run git: exit status 128

Error: failed to create repository autorest-diff4: failed to run gh: * Request at 2023-02-27 16:07:38.5218054 -0800 PST m=+0.100134501

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 15 (12 by maintainers)

Commits related to this issue

Most upvoted comments

@heaths I don’t have a lot more context than you do, but it seems likely this was done as an optimization for empty repos. Before template repos support there was no git fetch just the git init and git remote add, which makes sense as that would be faster than doing a git clone.

For template repos, since we need to get the remote files, I would suggest we treat that case the same as if a license or git ignore template was specified, meaning that if a template is specified we go down the git clone code path. What do you think?

Line 390 of create.go would change to

if opts.LicenseTemplate == "" && opts.GitIgnoreTemplate == "" && opts.Template == "" {

That way all these template options are treated the same and we can add the backoff/retry code around the git.Clone as we have done in other places.

I’m happy to take this one.