Git使用问题与解决方法

本文记录一些使用Git过程中遇到的问题及其解决办法,如无特别提及,所用环境为git version 2.25.1/Ubuntu 20.04 x64。

git clone时出现302错误

问题现象

执行命令git clone https://XXX.git test,出现如下提示

1
2
3
Cloning into 'test'...
error: RPC failed; HTTP 302 curl 22 The requested URL returned error: 302
fatal: the remote end hung up unexpectedly

解决过程

首先了解HTTP 302表示的是什么错误,通过学习了解到302错误表示被请求的资源暂时转移(Moved temporatily),服务器端会给出一个转移后的URL,此后,客户端应按照转移后的URL再次请求,一般浏览器都会自动处理这种情况。

那么git是如何处理http[s]的呢?从此条日志可以看到git使用了curl或libcurl来做http[s]的客户端的,另外回顾使用sudo apt-get install git命令安装git时,也可以看到安装了git、git-man、libcurl3-gnutls这3个包,因此,可以从curl的使用入手分析,先查看了git clone的手册(man git-clone),没有找到什么有用信息,继续看curl手册(man curl),在查找302这个关键时发现-L选项正是处理此种情况的,那么是不是因为git没有使用这样的选项才报错,应当如何指定这种选项?带着这种疑问继续查看git配置手册(man git-config),在检索了带有关键字curl或http的配置后,发现配置项http.followRedirects描述的是如何处理资源重定向的,按照文档描述,默认配置initial只跟随一次,而设置为true后会跟随任意重定向,因此,将此值设为true(git config --global http.followRedirects true)继续尝试,结果命令正常完成,问题得到解决。

在解决此问题的过程中,还了解到将GIT_CURL_VERBOSE环境变量设置为1(export GIT_CURL_VERBOSE=1)可以观察到整个curl处理http[s]的全过程,是个调试git报curl相关错误的方法。除此之外,导出另外两个环境变量(export GIT_TRACE_PACKET=1export GIT_TRACE=1)可以观察到更详细的过程,可以按需尝试一下。

git clone时出现curl 56 GnuTLS recv error (-9)错误

问题现象

执行命令git clone https://github.com/vim/vim.git,出现如下提示

1
2
3
4
5
6
7
8
9
Cloning into 'vim'...
remote: Enumerating objects: 172504, done.
remote: Counting objects: 100% (27/27), done.
remote: Compressing objects: 100% (17/17), done.
error: RPC failed; curl 56 GnuTLS recv error (-9): Error decoding the received TLS packet.
error: 3785 bytes of body are still expected
fetch-pack: unexpected disconnect while reading sideband packet
fatal: early EOF
fatal: fetch-pack: invalid index-pack output

解决过程

多次尝试发现,有的时候网速较快时也能成功,而从网络上收集来的资料看,GnuTLS方式出现了各种各样的问题,可以自行编译并使用OpenSSL。在Ubuntu上,由于官方包将git安装在/usr/bin/下面,保持官方的话,自行编译可以将prefix设为/usr/local,/usr/local/bin通常是优先于/usr/bin的,如此我们默认先使用自行编译的git,而用apt命令安装的命令和手册仍保留,以下是一个编译过程:

1
2
3
4
5
6
git clone git://git.kernel.org/pub/scm/git/git.git
git checkout v2.9.5
sudo apt install -y libssl-dev zlib1g-dev libexpat1-dev tcl gettext # 根据下面的编译错误提示,使用apt-file search和apt找到缺失的库并安装
sudo apt install -y libcurl4-openssl-dev # 关键,不使用libcurl4-gnutls-dev或libcurl4-nss-dev
make prefix=/usr/local/
sudo make prefix=/usr/local install

参考资料

  1. man git-clone
  2. man curl
  3. man git-config