使用libgit2(C++)提交推送时SSH报git_remote_connect错误
我之前在做libgit2的C++开发时,刚好碰到过和你完全一样的问题!HTTPS推送提交都没问题,一用SSH就报那个奇怪的git_remote_connect : Invalid command: 'XXX 'YYY/test.git''错误,还提示检查core.gitProxy和GIT_PROXY_COMMAND,折腾了好半天终于搞定了,给你说说我的解决思路和步骤:
问题根源拆解
这个错误本质是libgit2把SSH连接错误当成了代理请求,要么是你的代理配置干扰了SSH连接逻辑,要么是git_remote_callbacks里的凭证/回调配置有问题,导致SSH命令被错误解析成了代理指令。
具体解决步骤
1. 先确认SSH仓库URL格式正确
首先要排除最基础的错误:你的SSH URL必须是标准格式,不能混着git://或者有多余空格,比如:
- 正确格式:
git@github.com:YYY/test.git或者ssh://git@github.com/YYY/test.git - 错误格式:
git://git@github.com/YYY/test.git(这是git协议,不是SSH)
2. 强制清空代理相关配置
错误提示里明确提到了core.gitProxy和GIT_PROXY_COMMAND,所以不管你有没有手动设置过,都要在代码里强制清空这些配置,避免干扰SSH连接:
git_config *config; if (git_repository_config(&config, repo) == 0) { // 清空core.gitProxy配置 git_config_set_string(config, "core.gitProxy", ""); // 如果有http.proxy也可以一并清空,防止影响 git_config_set_string(config, "http.proxy", ""); git_config_free(config); }
另外,也要确保你的程序运行环境里没有设置GIT_PROXY_COMMAND环境变量,可以在代码里手动 unset:
unsetenv("GIT_PROXY_COMMAND");
3. 正确配置git_remote_callbacks的SSH凭证回调
这是最关键的一步!之前我的问题就是因为凭证回调没正确设置,导致libgit2 fallback到了错误的连接逻辑。你需要为SSH专门配置凭证获取回调:
示例代码:
// SSH凭证获取回调:用密钥认证(推荐) int ssh_credential_callback(git_cred **out, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) { // 如果URL里已经带了用户名(比如git@xxx.com),username_from_url会自动获取到 const char *username = username_from_url ? username_from_url : "git"; // 使用本地的SSH私钥路径,比如~/.ssh/id_rsa return git_cred_ssh_key_new(out, username, nullptr, "/home/your-user/.ssh/id_rsa", nullptr); // 如果用密码认证,替换成下面这行: // return git_cred_userpass_plaintext_new(out, username, "your-ssh-password"); } // 证书检查回调:跳过或验证SSH证书(避免连接时证书报错) int ssh_cert_check_callback(git_cert *cert, int valid, const char *host, void *payload) { // 如果你信任目标主机,可以直接返回0(允许连接) // 生产环境建议做证书验证,这里只是示例 return 0; } // 初始化并设置回调 git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; callbacks.credentials = ssh_credential_callback; callbacks.certificate_check = ssh_cert_check_callback; // 注意:不要设置proxy相关的回调!比如callbacks.proxy = ... 这会干扰SSH连接 // 连接远程仓库 int connect_err = git_remote_connect(remote, GIT_DIRECTION_PUSH, &callbacks, nullptr, nullptr); if (connect_err < 0) { const git_error *err = git_error_last(); printf("SSH连接错误: %s\n", err->message); }
4. 确认libgit2的SSH编译特性
如果上面的步骤都没用,检查你的libgit2是否编译了OpenSSH支持:
unsigned int features = git_libgit2_features(); if (!(features & GIT_FEATURE_SSH)) { printf("警告:当前libgit2版本未编译SSH支持!"); }
如果没有SSH特性,你需要重新编译libgit2时开启OpenSSH支持(比如用-DUSE_SSH=ON的CMake参数)。
最后总结
我当时就是因为代理配置没清空,加上凭证回调没正确设置,才导致了那个奇怪的命令解析错误。按照上面的步骤调整后,SSH连接和推送就完全正常了,你可以一步步排查试试!
内容的提问来源于stack exchange,提问作者Biancasta

