Short answers
Which Git setting selects an HTTP proxy?
http.proxy selects a proxy for Git’s HTTP and HTTPS transport. An HTTPS repository can use an HTTP gateway through CONNECT. An SSH remote uses a different transport and is not configured by this setting.
Can Git ask for the proxy password?
Yes. A proxy URL containing a username without a password tells Git to obtain the password through its credential mechanism. The isolated example below removes saved helpers and asks on the terminal.
Does ls-remote prove that a clone will finish?
No. It reads advertised references. Downloading repository objects is a further check, and submodules, large-file downloads and build tools can use additional hosts or clients.
Should I disable SSL verification for a Git proxy?
No. Check which connection failed, the certificate hostname and its trust chain. Use an approved CA file when necessary; a proxy password cannot repair a certificate error.
Check the repository transport first
| Repository address | Meaning |
|---|---|
| https://git.example.org/team/project.git | Git uses HTTPS. The HTTP proxy receives a CONNECT request, then the destination TLS connection runs through that tunnel. |
| http://git.example.org/team/project.git | Git uses HTTP without destination TLS. Prefer the repository’s supported HTTPS address. |
| ssh://git@git.example.org/team/project.git or git@git.example.org:team/project.git | Git uses SSH. The HTTP settings in this guide do not configure that SSH connection. |
Use a repository you own or are permitted to read and an approved gateway. The example addresses above are placeholders. If an organisation requires SSH, follow its approved SSH configuration; do not change the transport merely to work around its access policy. Git documents the supported remote URL forms.
For Portproof, select HTTP in the connection builder and keep the full generated username, gateway and HTTP port together. Current pool and country choices come from locations. This is shared proxy traffic; repository access remains controlled by the repository owner.
Read the remote references with temporary settings
Use supported Git and Python 3 installations in a macOS or Linux terminal. Start with a repository that needs no repository login, if one is available for your authorised test. Save the following script as git-proxy-check.py. It changes settings only for its Git child process and does not load your usual Git configuration, proxy exclusions, credential helpers or tracing variables.
git --version
python3 --version
python3 git-proxy-check.py check 'https://git.example.org/team/project.git'Enter the complete proxy username at the hidden prompt. Git then displays a password prompt naming the proxy: check that hostname before entering its original password. A later prompt naming the repository requires repository credentials instead. Cancel an unexpected prompt; never enter the proxy password for the repository host.
import getpass
import os
from pathlib import Path
import shutil
import subprocess
import sys
import tempfile
from urllib.parse import quote, urlsplit
import warnings
def run_check(repository, server, username, destination=None, ca_file=None):
for value in (repository, server):
if any(ord(c) <= 32 or ord(c) == 127 for c in value):
raise ValueError("Invalid URL")
repo = urlsplit(repository)
proxy = urlsplit(server)
if (repo.scheme != "https" or not repo.hostname or repo.username is not None
or repo.password is not None or repo.query or repo.fragment):
raise ValueError("Use an HTTPS repository URL without credentials")
if (proxy.scheme != "http" or not proxy.hostname or proxy.port is None
or proxy.username is not None or proxy.password is not None
or proxy.path not in ("", "/") or proxy.query or proxy.fragment):
raise ValueError("Use an HTTP gateway with its port, without credentials")
if not username or ":" in username or any(ord(c) < 33 or ord(c) > 126 for c in username):
raise ValueError("Use the complete printable proxy username without spaces")
git = shutil.which("git")
if not git:
raise ValueError("Git was not found")
target = Path(destination).resolve() if destination else None
if target and (target.exists() or not target.parent.is_dir()):
raise ValueError("Choose a new clone directory with an existing parent")
ca = str(Path(ca_file).resolve(strict=True)) if ca_file else None
with tempfile.TemporaryDirectory(prefix="git-proxy-check-") as directory:
template = Path(directory, "empty-template")
template.mkdir()
child_env = {
"PATH": os.defpath, "HOME": directory, "XDG_CONFIG_HOME": directory,
"GIT_CONFIG_NOSYSTEM": "1", "GIT_CONFIG_SYSTEM": os.devnull,
"GIT_CONFIG_GLOBAL": os.devnull, "GIT_CEILING_DIRECTORIES": directory,
"GIT_TERMINAL_PROMPT": "1", "LC_ALL": "C",
}
command = [
git, "-c", "credential.helper=",
"-c", "http.proxy=http://" + quote(username, safe="") + "@" + proxy.netloc,
"-c", "http.sslVerify=true", "-c", "http.followRedirects=false",
"-c", "protocol.allow=never", "-c", "protocol.https.allow=always",
"-c", "core.hooksPath=" + os.devnull,
]
if ca:
command += ["-c", "http.sslCAInfo=" + ca]
if target:
command += ["clone", "--depth=1", "--no-checkout",
"--template=" + str(template), "--", repository, str(target)]
else:
command += ["ls-remote", "--exit-code", repository, "HEAD"]
# Git itself asks for the password on the terminal. No password argument,
# environment variable, credential helper or password file is supplied.
return subprocess.run(command, cwd=directory, env=child_env, check=False).returncode
def main():
if os.name != "posix" or not sys.stdin.isatty():
raise ValueError("Run in a macOS or Linux terminal")
if len(sys.argv) not in (3, 4) or sys.argv[1] not in ("check", "clone"):
raise ValueError("Usage: git-proxy-check.py check URL | clone URL NEW_DIRECTORY")
mode, repository = sys.argv[1:3]
if (mode == "clone") != (len(sys.argv) == 4):
raise ValueError("Only clone takes a new directory")
with warnings.catch_warnings():
warnings.simplefilter("error", getpass.GetPassWarning)
username = getpass.getpass("Full proxy username (hidden): ")
return run_check(repository, os.environ.get("PROXY_SERVER", "http://gw.portproof.org:7000"),
username, sys.argv[3] if mode == "clone" else None,
os.environ.get("GIT_CHECK_CA"))
if __name__ == "__main__":
try:
sys.exit(main())
except (ValueError, OSError, EOFError, KeyboardInterrupt, getpass.GetPassWarning):
print("Check stopped. Verify the URLs, terminal and destination directory.")
sys.exit(1)
Git’s proxy configuration documents the username-only URL. Its credential rules explain how a terminal prompt is chosen. The password stays out of command arguments, environment variables and saved configuration in this example. The username remains visible in Git’s process arguments and password prompt; use a trusted machine and keep terminal recordings out of shared logs.
The script has no total elapsed-time deadline. Use Ctrl-C to stop an unresponsive check. It disables redirects for a predictable starting target: use the repository owner’s final HTTPS clone URL if the server redirects. These choices are diagnostic settings, not a complete unattended job configuration.
Interpret the reference result before cloning
<commit-id> HEADA commit ID followed by HEAD with exit status 0 means this invocation read that reference. With --exit-code, status 2 means no matching reference was advertised; an empty repository or missing HEAD needs investigation before calling the proxy broken. Other failures need their error context. The ls-remote reference explains this distinction.
Our local Git 2.50.1 check read HEAD through an authenticated CONNECT proxy and separately cloned a synthetic repository. A rejected password prevented the repository request, an untrusted certificate failed with verification enabled, and an approved local CA allowed the request. These are client-behaviour checks, not a live gateway, location or throughput measurement.
After a successful reference check, choose a new destination whose parent already exists. The clone leaves downloaded Git data in that destination. Review or remove that specific directory if the run fails; never delete an existing working repository to retry this diagnostic.
python3 git-proxy-check.py clone 'https://git.example.org/team/project.git' /absolute/path/to/new-check-directoryThe sample uses --depth=1 and --no-checkout, an empty template and disabled hooks. It does not request submodules or materialise a working tree. A shallow clone can still transfer a large object set; one commit is not a byte limit. The clone options describe the reduced history. Later checkout, large-file tools, submodules and builds remain separate operations to authorise and test.
Separate gateway, TLS and repository failures
| Observation | What to check |
|---|---|
| Cannot resolve or connect to the proxy | Check the selected gateway and HTTP port from this worker. A different computer’s successful request does not establish this path. |
| 407 or CONNECT authentication refused | Check the full proxy username, password, balance and gateway error code when available. Repository credentials do not authenticate the proxy. |
| Certificate verification fails after CONNECT | Check the repository hostname, certificate chain and approved trust. Keep verification enabled. |
| Repository 401, 403 or repository not found | Confirm the exact repository URL and read permission. Some services conceal a restricted repository behind a not-found response. |
| Reference check succeeds; clone fails | Check the object transfer and server response. A successful reference request does not test a complete pack download. |
| The isolated check works; the normal command fails | Compare the actual remote transport, saved configuration and environment used by that command. |
Use the 407 guide for gateway authentication, CONNECT diagnostics for tunnel refusals and the certificate guide for trust failures. An HTTP gateway’s CONNECT tunnel and a TLS connection to an HTTPS proxy are different layers; this script accepts an HTTP gateway only.
HTTP proxy authentication is carried on the connection to the gateway; the repository’s HTTPS tunnel does not encrypt that earlier HTTP hop. Use an approved network path. Do not turn off certificate checks, paste token-bearing URLs into commands or share credential-bearing traces to make a failing check easier to diagnose.
Apply the result to the actual Git workflow
Git can read system, user, repository and command settings, plus environment variables. The Git environment reference explains the configuration controls used here. Outside the script, a URL-specific HTTP setting, remote-specific proxy, proxy exclusion or URL rewrite can change the result. Inspect those locally; even configuration key names can contain repository addresses, so avoid sharing a full dump.
Keep a password out of git config, remote URLs and shell history. For repeated or unattended access, use your organisation’s reviewed credential helper or secret integration and verify its proxy-host context separately from the repository-host context. The terminal-only script deliberately does not read or save a helper credential and cannot validate that automation setup.
The position of -c matters: git -c key=value clone … supplies a Git command setting, while git clone -c key=value … writes a setting into the new repository. Our example uses the first form, so the proxy does not remain configured in the cloned repository. Subsequent commands need their own approved configuration.
An npm registry ping, pip index query or curl check does not verify Git dependencies. Test the actual Git process before returning to the package manager. Measure a representative permitted transfer with traffic accounting, then review current proxy options if this route fits the workload.
What is not allowed
Read or clone only repositories you are authorised to access, through an approved route. Respect repository terms, network policy and the acceptable-use policy.
Read next
npm CLI proxy setup and connection checks
Check the npm registry through an HTTP proxy with isolated settings, prompted credentials and strict TLS verification.
Read the guide
Fix proxy certificate errors in curl
Identify the failing TLS layer, check the hostname and trust source, and interpret bounded curl results.
Read the guide