Published on

坑爹 -- Ubuntu 版的 Git 使用的 GnuTLS 而不是 OpenSSL 提供的 TLS 实现

Authors
  • avatar
    Name
    ttyS3
    Twitter

起因

为什么用的是Ubuntu? 老灯你不是喜欢ArchLinux的么? 没错,这个Ubuntu只是老灯在工作环境使用的, 主要是团队要求。与大家保持一致。

当前我的neovim还是用的Vim Plug这个插件管理器(已经在着手准备迁移到init.lua + packer.nvim 了)。 在更新neovim 插件时(:PlugUpdate ) 遇到了以下错误:

x vim-startify:
    fatal: unable to access 'https://github.com/mhinz/vim-startify.git/': gnutls_handshake() failed: The TLS connection was non-properly terminated.

gnutls_handshake() failed 非常吸睛,因为我之前在Arch和 Fedora 上使用Git 都从来不会遇到这个错误的。

再跑了下更新命令,抓取到了真正命令:

/usr/lib/git-core/git-remote-https origin https://github.com/mhinz/vim-startify.git

看来Ubuntu版的git-remote-https用的GnuTLS, 然后验证一下,果然中招了:

❯ ldd /usr/lib/git-core/git-remote-https | grep curl
        libcurl-gnutls.so.4 => /lib/x86_64-linux-gnu/libcurl-gnutls.so.4 (0x00007fc39a56b000)

编译启用 openssl 支持的 Git

当然了,这种事情,老灯不可能是第一个发现的,gist里有无数“修复”这个问题的shell脚本。 Github上也有。老灯找到一个不错了: https://github.com/paul-nelson-baker/git-openssl-shellscript fork 之,增加了多线程下载支持和多核心编译支持。毕竟,要速度嘛。

老灯的仓库在这: https://github.com/ttys3/git-openssl-shellscript

这个脚本会卸载Ubuntu自带的git (同时也会卸载git-flow), 在此之前我们先记录下原版git的样子吧:

git --version
git version 2.27.0

sudo apt info git
Package: git
Version: 1:2.27.0-1ubuntu1
Priority: optional
Section: vcs
Origin: Ubuntu
Maintainer: Ubuntu Developers <[email protected]>
Original-Maintainer: Jonathan Nieder <[email protected]>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 39.2 MB
Provides: git-completion, git-core
Depends: libc6 (>= 2.28), libcurl3-gnutls (>= 7.56.1), libexpat1 (>= 2.0.1), libpcre2-8-0 (>= 10.22), zlib1g (>= 1:1.2.0), perl, liberror-perl, git-man (>> 1:2.27.0), git-man (<< 1:2.27.0-.)
Recommends: ca-certificates, patch, less, ssh-client
Suggests: gettext-base, git-daemon-run | git-daemon-sysvinit, git-doc, git-el, git-email, git-gui, gitk, gitweb, git-cvs, git-mediawiki, git-svn
Breaks: bash-completion (<< 1:1.90-1), cogito (<= 0.18.2+), dgit (<< 5.1~), git-buildpackage (<< 0.6.5), git-core (<< 1:1.7.0.4-1.), gitosis (<< 0.2+20090917-7), gitpkg (<< 0.15), gitweb (<< 1:1.7.4~rc1), guilt (<< 0.33), openssh-client (<< 1:6.8), stgit (<< 0.15), stgit-contrib (<< 0.15)
Replaces: git-core (<< 1:1.7.0.4-1.), gitweb (<< 1:1.7.4~rc1)
Homepage: https://git-scm.com/
git clone https://github.com/ttys3/git-openssl-shellscript.git
cd git-openssl-shellscript

./compile-git-with-openssl.sh --skip-tests

编译安装完,检查下:

git --version
git version 2.31.0-rc1

没找到git-remote-https 在哪,随便clone个大仓库(为我们ps | grep 争取时间),然后找出来路径。

# 并不是真正要clone内核源码。。。
❯git clone https://github.com/torvalds/linux.git

# 新开另一个tab找路径
ps aux | grep 'torvalds/linux'
ttys3    2887728  0.0  0.0  15060  3964 pts/18   S+   16:17   0:00 /usr/libexec/git-core/git remote-https origin https://github.com/torvalds/linux.git
ttys3    2887729  4.0  0.0 108636 14272 pts/18   R+   16:17   0:00 /usr/libexec/git-core/git-remote-https origin https://github.com/torvalds/linux.git

# 找到了,看看
❯ ldd /usr/libexec/git-core/git-remote-https | grep libcurl
        libcurl.so.4 => /lib/x86_64-linux-gnu/libcurl.so.4 (0x00007ff2e529d000)

这次我们依赖的是libcurl4-openssl-dev (而不是libcurl4-gnutls-dev

❯ dpkg -L libcurl4-openssl-dev ... /usr/lib/x86_64-linux-gnu/libcurl.so ...


## troubleshoot

编译的时候,由于要查找原包的依赖,因此需要启动apt仓库的 `deb-src` 源。

ensure you have `deb-src` enabled in `/etc/apt/sources.list`

以下是老灯的配置(Ubuntu 20.10):

```shell
❯ cat /etc/apt/sources.list | grep -v '#'

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy main restricted
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy main restricted

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-updates main restricted
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-updates main restricted

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy universe
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy universe

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-updates universe
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-updates universe

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy multiverse
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy multiverse

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-updates multiverse
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-updates multiverse

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-backports main restricted universe multiverse
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-backports main restricted universe multiverse


deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-security main restricted
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-security main restricted

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-security universe
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-security universe

deb https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-security multiverse
deb-src https://mirrors.sjtug.sjtu.edu.cn/ubuntu groovy-security multiverse

新版本的Git 提升将默认的master 分支修改为 main (美国黑人运动的结果,影响无处不在啊,据说Mysql也要把主从同步里的相关术语里的master和slave改掉呢)

git init .
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>

得,那就配置一下吧, git config --global init.defaultBranch main

main 还能少打一个字节。