-
Notifications
You must be signed in to change notification settings - Fork 7.5k
[gh repo clone] Add --no-upstream flag
#10608
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
base: trunk
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
--no-upstream flag
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -27,6 +27,7 @@ type CloneOptions struct { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GitArgs []string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Repository string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UpstreamName string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NoUpstream bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func NewCmdClone(f *cmdutil.Factory, runF func(*CloneOptions) error) *cobra.Command { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -40,7 +41,7 @@ func NewCmdClone(f *cmdutil.Factory, runF func(*CloneOptions) error) *cobra.Comm | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd := &cobra.Command{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DisableFlagsInUseLine: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Use: "clone <repository> [<directory>] [-- <gitflags>...]", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Use: "clone <repository> [<directory>] [flags] [-- <gitflags>...]", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: cmdutil.MinimumArgs(1, "cannot clone: repository argument required"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Short: "Clone a repository locally", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Long: heredoc.Docf(` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -60,6 +61,9 @@ func NewCmdClone(f *cmdutil.Factory, runF func(*CloneOptions) error) *cobra.Comm | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| the remote after the owner of the parent repository. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| If the repository is a fork, its parent repository will be set as the default remote repository. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| To disable the addition of the %[1]supstream%[1]s remote for a forked repository, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use the %[1]s--no-upstream%[1]s flag. For a non-forked repository, this flag has no effect. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| If the repository is a fork, its parent repository will be added as an additional | |
| git remote called %[1]supstream%[1]s. The remote name can be configured using %[1]s--upstream-remote-name%[1]s. | |
| The %[1]s--upstream-remote-name%[1]s option supports an %[1]s@owner%[1]s value which will name | |
| the remote after the owner of the parent repository. | |
| If the repository is a fork, its parent repository will be set as the default remote repository. | |
| To disable the addition of the %[1]supstream%[1]s remote for a forked repository, | |
| use the %[1]s--no-upstream%[1]s flag. For a non-forked repository, this flag has no effect. |
iamazeem marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: I believe these changes create a situation where forked repositories are not resolved properly via remotes as gh repo view fails. 🤔
I want to raise this up with the other maintainers as I'm unsure if we still need to set remote resolution even though there is only 1 remote.
Demo
Repository: https://github.com/andyfeller/cli
$ make clean && make
rm -rf bin share
go build -trimpath -ldflags "-X github.com/cli/cli/v2/internal/build.Date=2025-04-14 -X github.com/cli/cli/v2/internal/build.Version=v2.68.1-23-g1bb599c1e " -o bin/gh ./cmd/gh
$ alias gh=$(realpath bin/gh)
$ cd ~/Documents/workspace/andyfeller
$ gh repo clone andyfeller/cli --no-upstream
Cloning into 'cli'...
remote: Enumerating objects: 56037, done.
remote: Total 56037 (delta 0), reused 0 (delta 0), pack-reused 56037 (from 1)
Receiving objects: 100% (56037/56037), 29.54 MiB | 22.13 MiB/s, done.
Resolving deltas: 100% (38350/38350), done.
$ cd cli
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/andyfeller/cli.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "trunk"]
remote = origin
merge = refs/heads/trunk
$ gh repo view
X No default remote repository has been set. To learn more about the default repository, run: gh repo set-default --help
please run `gh repo set-default` to select a default remote repository.Looking at GH_DEBUG=api output below, the RepositoryNetwork GraphQL query points to logic that resolves the remotes:
Expand for full GH_DEBUG=api gh repo view output
$ GH_DEBUG=api gh repo view
[git remote -v]
[git config --get-regexp ^remote\..*\.gh-resolved$]
* Request at 2025-04-14 11:44:42.424889 -0400 EDT m=+0.084322709
* 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 ████████████████████
> Content-Length: 388
> Content-Type: application/json; charset=utf-8
> Graphql-Features: merge_queue
> Time-Zone: America/New_York
> User-Agent: GitHub CLI v2.68.1-23-g1bb599c1e
GraphQL query:
fragment repo on Repository {
id
name
owner { login }
viewerPermission
defaultBranchRef {
name
}
isPrivate
}
query RepositoryNetwork {
viewer { login }
repo_000: repository(owner: "andyfeller", name: "cli") {
...repo
parent {
...repo
}
}
}
GraphQL variables: null
< 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: Mon, 14 Apr 2025 15:44:42 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.v4; param=merge-info-preview.nebula-preview; format=json
< X-Github-Request-Id: C7FB:2D65EB:521533D:A3DF8F7:67FD2D6A
< X-Oauth-Client-Id: 178c6fc778ccc68e1d6a
< X-Oauth-Scopes: admin:org, gist, repo, workflow
< X-Ratelimit-Limit: 5000
< X-Ratelimit-Remaining: 5000
< X-Ratelimit-Reset: 1744645618
< X-Ratelimit-Resource: graphql
< X-Ratelimit-Used: 476
< X-Xss-Protection: 0
{
"data": {
"viewer": {
"login": "andyfeller"
},
"repo_000": {
"id": "R_kgDOMUqY2A",
"name": "cli",
"owner": {
"login": "andyfeller"
},
"viewerPermission": "ADMIN",
"defaultBranchRef": {
"name": "trunk"
},
"isPrivate": false,
"parent": {
"id": "MDEwOlJlcG9zaXRvcnkyMTI2MTMwNDk=",
"name": "cli",
"owner": {
"login": "cli"
},
"viewerPermission": "ADMIN",
"defaultBranchRef": {
"name": "trunk"
},
"isPrivate": false
}
}
}
}
* Request took 478.958417ms
X No default remote repository has been set. To learn more about the default repository, run: gh repo set-default --help
please run `gh repo set-default` to select a default remote repository.Lines 61 to 109 in 408e21e
| func (r *ResolvedRemotes) BaseRepo(io *iostreams.IOStreams) (ghrepo.Interface, error) { | |
| if r.baseOverride != nil { | |
| return r.baseOverride, nil | |
| } | |
| if len(r.remotes) == 0 { | |
| return nil, errors.New("no git remotes") | |
| } | |
| // if any of the remotes already has a resolution, respect that | |
| for _, r := range r.remotes { | |
| if r.Resolved == "base" { | |
| return r, nil | |
| } else if r.Resolved != "" { | |
| repo, err := ghrepo.FromFullName(r.Resolved) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return ghrepo.NewWithHost(repo.RepoOwner(), repo.RepoName(), r.RepoHost()), nil | |
| } | |
| } | |
| if !io.CanPrompt() { | |
| // we cannot prompt, so just resort to the 1st remote | |
| return r.remotes[0], nil | |
| } | |
| repos, err := r.NetworkRepos(defaultRemotesForLookup) | |
| if err != nil { | |
| return nil, err | |
| } | |
| if len(repos) == 0 { | |
| return r.remotes[0], nil | |
| } else if len(repos) == 1 { | |
| return repos[0], nil | |
| } | |
| cs := io.ColorScheme() | |
| fmt.Fprintf(io.ErrOut, | |
| "%s No default remote repository has been set. To learn more about the default repository, run: gh repo set-default --help\n", | |
| cs.FailureIcon()) | |
| fmt.Fprintln(io.Out) | |
| return nil, errors.New( | |
| "please run `gh repo set-default` to select a default remote repository.") | |
| } |
Lines 130 to 162 in 408e21e
| // NetworkRepos fetches info about remotes for the network of repos. | |
| // Pass a value of 0 to fetch info on all remotes. | |
| func (r *ResolvedRemotes) NetworkRepos(remotesForLookup int) ([]*api.Repository, error) { | |
| if r.network == nil { | |
| err := resolveNetwork(r, remotesForLookup) | |
| if err != nil { | |
| return nil, err | |
| } | |
| } | |
| var repos []*api.Repository | |
| repoMap := map[string]bool{} | |
| add := func(r *api.Repository) { | |
| fn := ghrepo.FullName(r) | |
| if _, ok := repoMap[fn]; !ok { | |
| repoMap[fn] = true | |
| repos = append(repos, r) | |
| } | |
| } | |
| for _, repo := range r.network.Repositories { | |
| if repo == nil { | |
| continue | |
| } | |
| if repo.Parent != nil { | |
| add(repo.Parent) | |
| } | |
| add(repo) | |
| } | |
| return repos, nil | |
| } |
Uh oh!
There was an error while loading. Please reload this page.