ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CentOS 7源码编译升级Git到2.42.0:踩坑记录与完整指南

CentOS 7源码编译升级Git到2.42.0:踩坑记录与完整指南 如果你还在CentOS 7上守着yum默认的git 1.8.3那咱们必须聊聊。我最近在一台CentOS 7.9 minimal虚拟机里搭CI环境需要把git从1.8.3升到2.42.0。RPM包找不到合适的新版本只能走源码构建。这条路其实不难但我前后折腾了两个多小时踩了四个坑依赖没装全、configure检测不到curl、make到一半卡死、装完之后git命令还是旧的。今天把这几个坑按顺序捋一遍把解决过程、报错特征、为什么这么改都写清楚省得后面的人再交学费。1. 为什么偏要源码构建git不装二进制包的理由1.1 yum仓库里git版本老旧带来的实际问题CentOS 7自带的git版本是1.8.3.1这是2013年前后发布的版本距离现在已经快十年了。很多人觉得“git就是提交代码老版本也能用”真到实际用的时候才会发现有多难受。我在CI流水线里想用git switch和git restore这俩命令在git 2.23才正式成为稳定命令1.8.3压根不认识。想用git branch -m重命名分支在老版本里只能一步步git branch -M配合删除旧分支麻烦到怀疑人生。更别提一些现代的CI/CD脚本会直接调用git rebase --autosquash、git maintenance这类命令老版本要么报参数错误要么完全没有这个子命令。除了功能缺失老版本在性能和安全上也吃亏。git的对象格式、加密哈希算法在后续版本里做了大量改进1.8.3对SHA-256仓库完全不支持对部分HTTP/HTTPS协议的处理也存在已知问题。如果你只是写写笔记、管理几个小项目也许感受不明显但只要一上规模多个大仓库反复clone、fetch老版本在内存占用和传输效率上的短板就全暴露出来了。1.2 源码构建与二进制包的关键差异为什么不用现成二进制包因为CentOS 7的应用兼容性目标限制红帽官方仓库里基本不会同步最新版git。第三方源里确实有但引入第三方RPM源就等于要接受一套新的依赖和信任链在不能随便改源的生产环境里这是不被允许的。源码构建虽然多几步但有一个非常大的好处可以把git完整安装到独立目录比如/usr/local/git不影响系统自带的旧git也不会污染系统库。以后想升级直接解压新版编译替换就行整个工具链在自己的掌控下不用看发行版脸色。源码构建的代价也很明确需要处理编译依赖、同一台机器上有多个编译产物、PATH优先级混乱等问题。换句话说你付出的额外工作量本质上是在买“可控性”和“新鲜度”。如果你有明确的新版本需求或者你正好要在容器、虚拟机里做一次环境标准化源码构建是非常合理的选择。2. 准备工作环境清理与依赖补齐2.1 确认系统版本与基础编译工具动手之前先确认你的系统确实是我说的这种老CentOS环境。我这边是CentOS Linux release 7.9.2009核心版只带了minimal安装。执行cat /etc/redhat-release输出显示是CentOS 7.9。然后确认编译器是否存在gcc --version make --version如果提示找不到gcc直接装开发工具组。这是CentOS上最省事的做法一次性把编译常用的库和工具都拉进来yum groupinstall Development Tools这个命令会安装gcc、g、make、autoconf、automake、libtool等一整套工具。有人会问为什么不全用yum install gcc make这一条非得装整个组原因是git源码里的Makefile在很多目标里依赖autoconf生成configure脚本、perl模块打包、doc文档构建等只装gcc和make编译到一半大概率会蹦出“autoconf: command not found”这类错误。既然都选择从源码构建了没必要在这种基础依赖上省那一点硬盘空间。2.2 逐项安装git源码编译所需依赖装完开发工具组还缺几个关键的运行时库和开发头文件。git虽然是个版本管理软件但它不是完全自包含的很多功能要靠外部库支撑。我这次踩坑核心就是漏了这些包。正确的依赖安装命令如下yum install -y curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker perl-ExtUtils-CBuilder这几项不能省我逐个说下为什么需要curl-develgit通过libcurl实现HTTP/HTTPS远程仓库访问。如果编译时找不到curl-config最终装出来的git是没有httpsremote helper的克隆GitHub仓库时会直接报“Unable to find remote helper for https”。expat-devel这是XML解析库git的HTTP智能协议中处理服务器返回的XML响应时需要它。没有expat编译过程能通过但某些HTTP推送和fetch操作会失败。gettext-devel提供国际化翻译支持。不装的话make时可能因为缺少libintl而报错而且git的所有中文帮助文本都会丢失。openssl-develgit通过openssl实现TLS/SSL加密。显然git clone https地址、推送代码到远程都需要它。注意是-devel不是运行时的openssl。zlib-develgit对象数据库的压缩全靠zlib可以说是最核心的依赖之一。不装的话configure阶段就会挂掉。perl-ExtUtils-MakeMaker和perl-ExtUtils-CBuildergit的perl工具集如git send-email在构建时需要这两个perl模块。缺了它们make时经常遇到perl/PM.stamp错误非常让人抓狂。2.3 提前处理系统里已有git的影响CentOS 7默认自带git 1.8.3。源码构建时即便系统已存在老git也影响不大因为configure脚本会自动找我们的新源码。但有一个问题必须提前想清楚make install之后你希望git命令指向哪里如果直接把git安装到/usr/bin/git就会覆盖系统自带的版本。说实话这不推荐因为当yum更新或者其他rpm包依赖系统git时可能莫名奇妙地破坏二进制。更稳妥的方式是安装到/usr/local/git再通过修改PATH让新git优先被调用。我一开始偷懒直接./configure --prefix/usr等于覆盖了系统git。后来发现很多系统工具会调用系统中的git比如某些cron任务里用git拉代码会有版本不一致的风险。后来老老实实改成/usr/local/git世界清净了。3. 源码构建过程与踩坑实录3.1 下载解压对应版本的git源码从官方站点下载源码包。我用的是内核官方镜像wget -O git-2.42.0.tar.gz https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.42.0.tar.gz tar -xzf git-2.42.0.tar.gz cd git-2.42.0如果你在特殊网络环境里下载慢也可以使用国内高校或云厂商的软件镜像站文件名是一样的wget拉下来校验一下SHA-256就行。这一步看起来没技术含量但有个小坑某些旧版本tar不支持解压大文件或者长文件名其实CentOS 7的tar没这问题主要是别用tar -xzvf因为构建时如果磁盘空间不足解压和编译都会挂掉。建议先df -h看一下/和/tmp的使用情况源码编译需求至少准备2GB空闲空间。3.2 configure与make命令容易忽略的prefix和options进入源码目录后先执行configure./configure --prefix/usr/local/git --with-curl --with-openssl这里的--prefix决定了最终安装路径。--with-curl和--with-openssl是显式告诉configure启用这两项网络能力。虽然默认也可能会自动检测但显式指定能减少很多不确定因素。configure这一步非常重要它会打印一段summary类似$ ./configure --prefix/usr/local/git --with-curl --with-openssl ... * git version: 2.42.0 ... * prefix: /usr/local/git ... * libcurl: YES * expat: YES * openssl: YES * * host: x86_64-pc-linux-gnu重点关注libcurl、expat、openssl三行是不是YES。如果是NO说明依赖没装好后续编译出来的git功能不完整。我第一次configure时libcurl那行就显示NO因为只装了curl没装curl-devel。configure只是给我一个警告并没有直接中止所以一路make install之后git clone https://就失败了。如果configure过程中报错比如提示找不到某个头文件先看完整日志再决定补装依赖。configure脚本实际上很智能缺依赖时会给出提示比如configure: error: cannot find libcurl这就是缺curl-devel的典型报错。执行yum install curl-devel后重新configure即可。3.3 编译和安装实际上可能遇到的坑configure通过后执行make -j $(nproc)-j后面的数字是并行编译线程数。nproc返回CPU核数use it。第一个坑出现在这一步。我用的虚拟机分配了4核直接make -j4结果编译到一半终端开始疯狂报错都是类似submodule.c:25:19: fatal error: expat.h: No such file or directory我之前明明安装过expat怎么还是缺头文件后来发现系统里有两个expat一个系统自带一个来自开发工具组安装。configure重新运行后它找到了/usr/include/expat.h但make用的编译器头文件搜索路径却没包含这个目录。查了下发现是CPPFLAGS环境变量的问题。最简单粗暴的解决办法是把源码目录删干净重新解压、重新configure。因为configure会生成一系列config.h和Makefile它们依赖之前检测到的路径缓存如果中途改依赖缓存会骗人。第二个坑是内存不足。最小化CentOS 7虚拟机一般只给1GB或2GB内存编译git虽然不算吃内存大户但make -j4时多个编译器进程同时运行内存占用在1.5GB左右。系统没有内存交换分区时直接OOM进程被kill屏幕出现花屏式报错。解决办法是限制并行线程数或者干脆加大虚拟机内存。我在VirtualBox里把内存从1GB加到2GB然后改成make -j2顺利通过。第三个坑发生在make install之后。执行make install没有任何输出错误git --version却依然显示1.8.3。原因很直白/usr/local/git/bin不在PATH环境变量里。执行echo $PATH发现我的PATH里面只有/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin注意/usr/local/bin和/usr/local/git/bin完全是两码事。所以忽略这个问题。正确做法是把新路径加到PATH最前面export PATH/usr/local/git/bin:$PATH git --version这时才显示git version 2.42.0。但这样只对当前终端有效重开终端就失效。所以还要写进配置文件echo export PATH/usr/local/git/bin:$PATH /etc/profile.d/git.sh source /etc/profile.d/git.sh以后再登录系统git就是新版本了。3.4 验证安装是否可用版本号显示正确不代表就能正常工作。我建议建一个测试仓库实际跑一遍本地提交、分支切换、HTTP clone。可以先在本地验证mkdir /tmp/git-test cd /tmp/git-test git init echo hello README.md git add README.md git commit -m test commit git switch -c dev-branch git branch然后验证https远程访问git ls-remote https://github.com/git/git.git HEAD如果这条命令能返回远程的HEAD SHA-1说明libcurl和openssl都被正确编译进去了。我编译完第一次跑git ls-remote系统提示git: remote-https is not a git command. See git help.这个问题非常经典。原因是源码编译时没有安装libcurl-develconfigure自动跳过了HTTP支持所以git找不到remote-https这个helper。解决办法就是重新安装curl-devel然后重新configure、重新make install。4. 常见问题与排查技巧实录4.1 按症状分类configure阶段、make阶段、运行阶段下面这几个问题是我在实际安装过程中真实遇到的整理成表格方便速查阶段错误特征原因解决方法configureconfigure: error: cannot find libcurl缺curl或curl-develyum install curl curl-devel重新configureconfigureconfigure: error: zlib library not found缺zlib开发头文件yum install zlib zlib-develconfigureconfigure: error: expat library not found缺expat-develyum install expat-develmakefatal error: expat.h: No such file or directoryconfigure缓存了错误的头文件路径清理源码目录重新解压、重新configuremakemake: *** [perl/PM.stamp] Error 1缺少perl构建模块yum install perl-ExtUtils-MakeMaker perl-ExtUtils-CBuildermakevirtual memory exhausted或 OOM killed内存不足并行编译线程过多用make -j2增加虚拟机内存运行git: remote-https is not a git command编译时未启用curl支持安装curl-devel后重新configure生成运行fatal: unable to access https://...: SSL certificate problemCA证书库缺失或过期yum install ca-certificates或通过git config指定证书路径运行git --version仍显示老版本PATH没包含新路径修改/etc/profile.d/git.sh并source4.2 小技巧用config.log和config.status排查configure失败configure失败时很多人的第一反应是反复安装依赖包但这样效率很低。其实git源码的configure脚本极其啰嗦它会在当前目录生成一个config.log文件存了所有检测过程的详细输出。当configure报错时不要急着磨洋工先打开config.log搜索error或者checking相关的上下文。比如我看到的checking for CURL... no configure: error: in /root/git-2.42.0: configure: error: libcurl version 7.10.0 or later is required这就很明确了是libcurl版本不满足要求不是找不到。再看下面可以看到它调用了什么命令去检测。如果日志太乱也可以用grep -i error config.log | tail -20捞最后一段。另外configure生成的config.status文件里记录了本次configure最终启用的选项下次重跑configure时可以用它来对照参数省得自己记错。4.3 关于网络代理和镜像加速的实操心得如果你在公司内网或者校园网里下载源码包可能慢到怀疑人生。wget本身支持代理但默认不会主动走。你可以临时指定export http_proxyhttp://你的代理地址:端口 export https_proxyhttp://你的代理地址:端口 wget -O git.tar.gz https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.42.0.tar.gz下载完之后要记得unset http_proxy https_proxy否则在configure时检测网络相关功能可能会误判。因为有些检测会尝试连接外部地址代理设置不正确会导致出错。如果不想折腾代理用国内镜像源下载同样版本的git源码也是一种常见做法。镜像源只是文件内容一样校验SHA-256一致即可。下载命令可以是这样wget -O git.tar.gz https://mirrors.tuna.tsinghua.edu.cn/git/git-2.42.0.tar.gz注意有些镜像站的目录结构不一样最好先浏览一下实际目录。我之前凭印象拼URL下载回来一个404页面解压时它居然当成源码包解压了整个目录全是垃圾文件。这种事熟手也容易碰上所以下载完先file git.tar.gz确认是gzip压缩数据再继续。5. 把构建好的git接入日常工作流5.1 配置PATH并处理旧版本命令冲突安装完成后PATH优先级是下一个坑。我前面说到会写进/etc/profile.d/git.sh。这个思路适用于登录shell但如果你在脚本里用了非交互式shell/etc/profile.d/下的文件不一定被加载。比如CI脚本用#!/bin/bash执行默认是不读/etc/profile的这时git可能仍是系统老版本。更稳妥的办法是在~/.bashrc末尾追加同一行export PATH/usr/local/git/bin:$PATH但如果你的部署对象是机器上有很多服务账号那就不如直接在/usr/bin/git和/usr/bin/git可执行文件上做软链接强制所有进程都用新版本。做法如下mv /usr/bin/git /usr/bin/git.bak ln -s /usr/local/git/bin/git /usr/bin/git这样做的好处是命令解析器永远优先找/usr/bin不会误跑到其他地方坏处是yum升级系统git时如果rpm包校验二进制文件软链接可能被覆盖需要再恢复一下。我更推荐PATH方式毕竟很多后台任务已经缓存了环境变量改PATH比替换二进制文件要安全。5.2 git的全局配置与代理配置建议新git第一次提交时用户信息是空的必须设置git config --global user.name 你的名字 git config --global user.email youexample.com如果你需要针对某些仓库使用HTTP代理在git里设置也简单git config --global http.proxy http://代理地址:端口 git config --global https.proxy http://代理地址:端口至于SSL证书问题前面提到过yum install ca-certificates一般就能解决。如果你们公司内网有自己的根证书可以用git config --global http.sslCAInfo /opt/company-ca.crt这个配置比直接关掉http.sslVerify靠谱多了。我见过不少人为了省事直接在命令里加-c http.sslVerifyfalse这等于把自己的git完全暴露在中间人攻击下。不要学。5.3 后续升级和维护的经验编译安装git不是一锤子买卖。过个一年半载官方又出了新版本你的/usr/local/git下的git还停在2.42.0想升级怎么做其实很简单只需要重复一遍下载、解压、configure、make、make install新版本会覆盖旧版本文件不用担心卸载问题。但在执行make install前最好确认没有正在运行的git进程ps aux | grep git如果系统上有其他用户正在用git提交或者clone强制覆盖可执行文件可能会导致程序崩溃。我自己的习惯是升级前先发公告或者选在深夜没人用的时候操作。另外升级前先跑一下make clean个人建议不需要。直接在新源码目录里重新configure和make installold的二进制文件会被覆盖但配置文件如/etc/gitconfig会保留。如果你觉得自己把旧的安装目录搞得很乱也可以删除/usr/local/git后重新安装但这会丢掉自己的配置文件吗不会全局配置默认在/etc/gitconfig用户配置在~/.gitconfig都不在/usr/local/git里。如果你把git装到/usr/local/git后系统里同时存在新旧两套git时间长了容易忘记哪套对应哪个版本。一个小技巧是给自己的构建目录打标签/usr/local/git/bin/git --version并且写进README。以后换机器、换用户一眼就知道当前环境用的是哪套git。6. 一点个人体会源码构建git这件事第一次做的时候可能觉得“坑怎么这么多”但只要理解了几条核心逻辑后面就是重复劳动。我在实际安装中最大的体会是不要一上来就堆命令而是先让configure告诉你环境缺什么再针对性补依赖。几乎所有的编译失败最后都能归结到依赖不完整、configure缓存过期、内存不足这三类原因上。真正把这些原因记在心里换一台新机器重新搭环境五分钟就能跑通。最后再分享一个小技巧把依赖安装、configure参数、PATH配置写成一个shell脚本保存下来。下次无论是给新虚拟机搭环境还是给别人远程排查问题直接让脚本把环境恢复理想状态比你一步步在终端里敲命令要省事得多。当然脚本里尽量用系统自带命令避免引入不必要的复杂逻辑。编译工具链这种东西稳定压倒一切。
返回列表