Skip to content

gh repo rename myorg/newname results in myorg/myorg-newname #10034

Closed

Description

@johnstonmatt

Describe the bug

gh version 2.63.0 (2024-11-27)
https://github.com/cli/cli/releases/tag/v2.63.0

I renamed my repo using gh repo rename polyseam/frappe-containers, this resulted in the preview being correct:

? Rename polyseam/containers to polyseam/frappe-containers? Yes

but the result being wrong:

✓ Renamed repository polyseam/polyseam-frappe-containers

Steps to reproduce the behavior

  1. gh repo create org/foo-repo --private --clone
  2. cd foo-repo
  3. gh repo rename org/bar-repo
  4. note the confirm prompt is correct
  5. enter Yes
  6. note the incorrect result: "✓ Renamed repository org/org-bar-repo"

Expected vs actual behavior

The resulting repo name should not be prefixed with orgname- and should instead match the preview in step 4.

Logs

Paste the activity from your command line. Redact if needed.

Activity

  1. williammartin commented on Dec 7, 2024

    @williammartin
    Member

    Interesting! Thanks for the bug report. What's happening here is that the CLI is echoing your argument (which looks correct - but isn't, because repo rename doesn't expect an org in the name) but the API is converting the / to a -. Here's the API request body for a command I ran:

    ➜  test-repo git:(main) GH_DEBUG=api gh repo rename williammartin/test-repo-rename
    [git remote -v]
    [git config --get-regexp ^remote\..*\.gh-resolved$]
    ? Rename williammartin-test-org/test-repo to williammartin/test-repo-rename? Yes
    * Request at 2024-12-07 08:54:00.151523 +0100 CET m=+2.598041542
    * Request to https://api.github.com/repos/williammartin-test-org/test-repo
    > PATCH /repos/williammartin-test-org/test-repo HTTP/1.1
    > Host: api.github.com
    > Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
    > Authorization: token ████████████████████
    > Content-Length: 42
    > Content-Type: application/json; charset=utf-8
    > Time-Zone: Europe/Amsterdam
    > User-Agent: GitHub CLI 2.63.0
    
    {
      "name": "williammartin/test-repo-rename"
    }
    
    < 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
    < Cache-Control: private, max-age=60, s-maxage=60
    < Content-Security-Policy: default-src 'none'
    < Content-Type: application/json; charset=utf-8
    < Date: Sat, 07 Dec 2024 07:54:00 GMT
    < Etag: W/"a11a2851b506b1ab3658893d33c511135bf869881dcfda8ede6b83fc7f0c9e0a"
    < Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
    < Server: github.com
    < Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
    < Vary: Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With
    < X-Accepted-Oauth-Scopes:
    < X-Content-Type-Options: nosniff
    < X-Frame-Options: deny
    < X-Github-Api-Version-Selected: 2022-11-28
    < X-Github-Media-Type: github.v3; param=merge-info-preview.nebula-preview; format=json
    < X-Github-Request-Id: CA50:DCDAE:1C4A42F:1D1768C:6753FF18
    < X-Oauth-Client-Id: 178c6fc778ccc68e1d6a
    < X-Oauth-Scopes: codespace, delete_repo, gist, read:org, repo, workflow
    < X-Ratelimit-Limit: 15000
    < X-Ratelimit-Remaining: 14972
    < X-Ratelimit-Reset: 1733559751
    < X-Ratelimit-Resource: core
    < X-Ratelimit-Used: 28
    < X-Xss-Protection: 0
    
    {
      "id": 637760824,
      "node_id": "R_kgDOJgN1OA",
      "name": "williammartin-test-repo-rename",
      "full_name": "williammartin-test-org/williammartin-test-repo-rename",
    ...
    

    What we should probably do here is 1. document this more clearly in the help text 2. error if there is a / in the name. We could check if the name matches the org and ignore it but I don't know if it's that much better than just failing and introduces a bit of not-very-high-value maintenance and UX debt.

  2. BagToad commented on Dec 8, 2024

    @BagToad
    Member
    1. document this more clearly in the help text

    @williammartin I think this help doc change is important since this seems to come up from time to time. I opened a PR for this - it also includes a proposal for a small change to the prompt: #10044

  3. andyfeller commented on Dec 9, 2024

    @andyfeller
    Contributor

    Interesting! Thanks for the bug report. What's happening here is that the CLI is echoing your argument (which looks correct - but isn't, because repo rename doesn't expect an org in the name) but the API is converting the / to a -. Here's the API request body for a command I ran:

    What we should probably do here is 1. document this more clearly in the help text 2. error if there is a / in the name. We could check if the name matches the org and ignore it but I don't know if it's that much better than just failing and introduces a bit of not-very-high-value maintenance and UX debt.

    I hesitate on the level of intelligence that gh should exhibit here since the GitHub API is already doing some. It doesn't appear we have any repository name validation in the code base even for repository creation outside of splitting on slashes:

    func interactiveRepoNameAndOwner(client *http.Client, hostname string, prompter iprompter, defaultName string) (string, string, error) {
    name, err := prompter.Input("Repository name", defaultName)
    if err != nil {
    return "", "", err
    }
    name, owner, err := splitNameAndOwner(name)
    if err != nil {
    return "", "", err
    }
    if owner != "" {
    // User supplied an explicit owner prefix.
    return name, owner, nil
    }
    username, orgs, err := userAndOrgs(client, hostname)
    if err != nil {
    return "", "", err
    }
    if len(orgs) == 0 {
    // User doesn't belong to any orgs.
    // Leave the owner blank to indicate a personal repo.
    return name, "", nil
    }
    owners := append(orgs, username)
    sort.Strings(owners)
    selected, err := prompter.Select("Repository owner", username, owners)
    if err != nil {
    return "", "", err
    }
    owner = owners[selected]
    if owner == username {
    // Leave the owner blank to indicate a personal repo.
    return name, "", nil
    }
    return name, owner, nil
    }
    func splitNameAndOwner(name string) (string, string, error) {
    if !strings.Contains(name, "/") {
    return name, "", nil
    }
    repo, err := ghrepo.FromFullName(name)
    if err != nil {
    return "", "", fmt.Errorf("argument error: %w", err)
    }
    return repo.RepoName(), repo.RepoOwner(), nil
    }

    // FromFullName extracts the GitHub repository information from the following
    // formats: "OWNER/REPO", "HOST/OWNER/REPO", and a full URL.
    func FromFullName(nwo string) (Interface, error) {
    return FromFullNameWithHost(nwo, defaultHost())
    }
    // FromFullNameWithHost is like FromFullName that defaults to a specific host for values that don't
    // explicitly include a hostname.
    func FromFullNameWithHost(nwo, fallbackHost string) (Interface, error) {
    repo, err := repository.ParseWithHost(nwo, fallbackHost)
    if err != nil {
    return nil, err
    }
    return NewWithHost(repo.Owner, repo.Name, repo.Host), nil
    }

    Since the underlying cli/go-gh logic assumes the slashes are for [HOST/]OWNER/REPO, I think the safest things to do are:

    1. Error if repository name includes /
    2. Update documentation that repositories are kept within owning org/user account
  4. eviltimrogers commented on Jan 28, 2025

    @eviltimrogers

    I'd definitely agree that it feels like the right way forward to error if a repository name is entered beginning with /.

  5. williammartin commented on Feb 3, 2025

    @williammartin
    Member

    Acceptance Criteria

    Given I have a repo org/repo
    When I run gh repo -R org/repo rename org/repo-rename
    Then the CLI exits 1
    And Then I see an informative error message on stderr that the renamed repository should not contain forward slashes, and a hint that if the user is trying to move the repository between organisations they need to read the docs, with a link.

  6. added
    priority-3Affects a small number of users or is largely cosmetic
    and removed on Feb 3, 2025
  7. Randy88-art commented on Aug 17, 2025

    @Randy88-art

    Duplicate of #10466

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggh-reporelating to the gh repo commandhelp wantedContributions welcomepriority-3Affects a small number of users or is largely cosmetic

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions