Skip to content

Conversation

@fotoetienne
Copy link

Summary

Fixes #12179 - Allows gh pr checkout and related commands to work when git remote hostname differs from GitHub API hostname.

Problem

Commands like gh pr checkout, gh pr create, and gh repo fork fail in enterprise environments where:

  • Git operations route through git.company.com (proxy/bastion)
  • API operations target github.company.com (GitHub Enterprise)

Error encountered:

none of the git remotes configured for this repository correspond to the
GH_HOST environment variable

This affects legitimate enterprise configurations using git proxies, SSH bastions, or git mirrors.

Root Cause

The remote resolver in pkg/cmd/factory/remote_resolver.go returns an error when no git remotes match authenticated hosts, even though:

  • Git operations only need owner/repo matching (not hostname)
  • Git commands use remote name (origin), not the URL
  • API operations validate hostname separately via GH_HOST

The git remote hostname and API hostname are separate concerns.

Solution

Changed the remote resolver to fall back to all remotes when no remotes match authenticated hosts, rather than failing with an error.

Before:

if len(rr.cachedRemotes) == 0 {
    if isHostEnv(src) {
        rr.remotesError = fmt.Errorf("none of the git remotes configured...")
        return nil, rr.remotesError
    }
    // ... more error paths
}

After:

if len(rr.cachedRemotes) == 0 {
    // Fall back to all remotes for commands that only need owner/repo matching.
    // Commands performing API operations will still fail with clear errors when
    // the API host is wrong. This allows git operations through proxies/bastions
    // where the git remote host differs from the GitHub API host.
    rr.cachedRemotes = resolvedRemotes
}

Changes Made

  • Modified pkg/cmd/factory/remote_resolver.go:
    • Replaced error returns with fallback to all remotes (6 lines)
    • Removed unused fmt import

Testing

Test scenario:

# Git remote through proxy
$ git remote -v
origin  git@git.company.com:corp/repo.git

# Authenticated to GitHub Enterprise
$ gh auth login --hostname github.company.com
$ export GH_HOST=github.company.com

# This now works:
$ gh pr checkout 123
✓ Checks out PR successfully

Verified:

  • gh pr checkout works with mismatched hostnames
  • gh pr view, gh pr list still work (API operations)
  • ✅ Commands fail appropriately when API host is genuinely wrong
  • ✅ Backwards compatible with standard configurations

Real-world testing:

  • Tested in Netflix enterprise environment (git.netflix.net / github.netflix.net)
  • Successfully checked out PR [WIP] #2353 emoji parser #2407 in production repository
  • Wrapper script complexity reduced from ~220 lines to ~10 lines

Impact

Benefits:

  • ✅ Fixes legitimate enterprise git proxy configurations
  • ✅ Generic solution (not company-specific)
  • ✅ Minimal code change (6 lines)
  • ✅ No security impact (API auth still validated)
  • ✅ Backwards compatible
  • ✅ Clearer separation of concerns

Who this helps:

  • Enterprises using git proxies for security/auditing
  • Organizations with SSH bastions/jump hosts
  • Teams using git mirrors for performance
  • Any environment where git and API use different hostnames

Security Considerations

  • API host validation is unchanged - still enforced via GH_HOST and auth config
  • Authentication still required for all API operations
  • Only affects which remotes are considered for git operations
  • Git operations already require appropriate git credentials

Alternative Considered

Created a separate GitRemotes() factory method for git-only operations, but the fallback approach is simpler and achieves the same goal with less code.

@fotoetienne fotoetienne requested a review from a team as a code owner November 21, 2025 14:11
@github-actions
Copy link

Thank you for your pull request! 🎉

This PR appears to fix the following issues that are not labeled with help wanted Contributions welcome :

As outlined in our Contributing Guidelines, we expect that PRs are only created for issues that have been labeled help wanted.

While we appreciate your initiative, please note that:

  • PRs for non-help wanted issues may not be reviewed immediately as they might not align with our current priorities
  • The issue might already be assigned to a team member or planned for a specific release
  • We may need to close this PR. For example, if it conflicts with ongoing work or architectural decisions

What happens next:

  • Our team will review this PR and the associated issues
  • We may add the help wanted label to the issues, if appropriate, and review this pull request
  • In some cases, we may need to close the PR. For example, if it doesn't fit our current roadmap

Thank you for your understanding and contribution to the project! 🙏

This comment was automatically generated by cliAutomation.

@cliAutomation cliAutomation added the external pull request originating outside of the CLI core team label Nov 21, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes issue #12179 by allowing git operations to work when the git remote hostname differs from the GitHub API hostname, which is common in enterprise environments using git proxies or SSH bastions.

Key Changes:

  • Modified remote resolver to fall back to all remotes instead of failing when no remotes match authenticated hosts
  • Removed error paths that prevented legitimate enterprise configurations from working
  • Deleted unused fmt import after removing error formatting code

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +82 to +86
// Fall back to all remotes for commands that only need owner/repo matching.
// Commands performing API operations will still fail with clear errors when
// the API host is wrong. This allows git operations through proxies/bastions
// where the git remote host differs from the GitHub API host.
rr.cachedRemotes = resolvedRemotes
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

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

Falling back to all remotes without validation could allow commands to operate on unintended repositories. Consider adding a warning log or requiring explicit opt-in via configuration when operating in this fallback mode to make the behavior visible to users and prevent silent failures when configuration is genuinely incorrect.

Copilot uses AI. Check for mistakes.
Currently, gh rejects git remotes when their hostname doesn't match the
authenticated GitHub host, even though this is a legitimate enterprise
configuration. This prevents commands like `gh pr checkout` from working
in environments with git proxies or SSH bastions.

The validation is unnecessarily strict because:
- Git operations only need owner/repo matching, not hostname matching
- Git commands use the remote name (e.g., "origin"), not the URL
- API operations already validate the host separately via GH_HOST

This change allows all remotes to be considered when no remotes match
authenticated hosts. Commands performing API operations will still fail
appropriately with clear errors when the API host is wrong.

Fixes cli#12179

Real-world scenario this fixes:
- Git remote: git@git.company.com:corp/repo.git
- API endpoint: github.company.com
- Previously: "none of the git remotes configured" error
- Now: Works correctly for git operations

Changes:
- Remove strict hostname validation in remote resolver
- Fall back to all remotes for git operations
- Remove unused fmt import
@fotoetienne fotoetienne force-pushed the fix-git-proxy-remotes branch from 78008cc to 4d7b893 Compare November 21, 2025 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external pull request originating outside of the CLI core team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gh pr checkout fails when git remote host differs from GitHub API host

2 participants