FreeBSD 中文社区 2025 第二季度问卷调查
FreeBSD 中文社区(CFC)
VitePress 镜像站QQ 群 787969044视频教程Ⅰ视频教程Ⅱ
  • FreeBSD 从入门到追忆
  • 中文期刊
  • 状态报告
  • 发行说明
  • 手册
  • 网络文章集锦
  • 笔记本支持报告
  • Port 开发者手册
  • 架构手册
  • 开发者手册
  • 中文 man 手册
  • 文章
  • 书籍
  • FreeBSD 中文期刊
  • 编辑日志
  • 2025-123 下游项目
    • FreeBSD 发布工程:新主管上任
    • GhostBSD:从易用到挣扎与重生
    • BSD Now 与将来
    • 字符设备驱动教程(第三部分)
    • 学会走路——连接 GPIO 系统
    • FreeBSD 中对 SYN 段的处理
    • FreeBSD 2024 年秋季峰会
  • 2024-1112 虚拟化
    • 字符设备驱动程序教程(第二部分)
    • 面向 Linux 和 Windows 用户的 bhyve
    • Xen 与 FreeBSD
    • Wifibox:一种嵌入式虚拟化无线路由器
    • 嵌入式 FreeBSD:Fabric——起步阶段
    • DGP:一种新的数据包控制方法
    • 会议报告:我在都柏林的 EuroBSDCon 体验
  • 2024-0910 内核开发
    • 字符设备驱动程序教程
    • VPP 移植到了 FreeBSD:基础用法
    • 利用 Kyua 的 Jail 功能提升 FreeBSD 测试套件的并行效率
    • FreeBSD 上的 Valgrind
    • 嵌入式 FreeBSD:探索 bhyve
    • TCP/IP 历险记:FreeBSD TCP 协议栈中的 Pacing
    • 实用软件:实现无纸化(Paperless)
  • 2024-0708 存储与文件系统
    • FreeBSD 中的 NVMe-oF
    • FreeBSD iSCSI 入门
    • 使用 ZFS 原生加密保护数据
    • 嵌入式 FreeBSD:打造自己的镜像
    • TCP LRO 简介
    • 基于 Samba 的时间机器备份
  • 2024-0506 配置管理对决
    • 基本系统中的 mfsBSD
    • rdist
    • Hashicorp Vault
    • 在 GitHub 上向 FreeBSD 提交 PR
    • 悼念 Mike Karels
    • 2024 年 5-6 月来信
    • 嵌入式 FreeBSD 面包板
    • TCP/IP 历险记:TCP BBLog
    • 实用软件:开发定制 Ansible 模块
  • 2024-0304 开发工作流与集成
    • FreeBSD 内核开发工作流程
    • FreeBSD 与 KDE 持续集成(CI)
    • 更现代的内核调试工具
    • 从零开始的 ZFS 镜像及 makefs -t zfs
    • 提升 Git 使用体验
  • 2024-0102 网络(十周年)
    • FreeBSD 中的 RACK 栈和替代 TCP 栈
    • FreeBSD 14 中有关 TCP 的更新
    • if_ovpn 还是 OpenVPN
    • SR-IOV 已成为 FreeBSD 的重要功能
    • FreeBSD 接口 API(IfAPI)
    • BATMAN:更优的可移动热点网络方式
    • 配置自己的 VPN——基于 FreeBSD、Wireguard、IPv6 和广告拦截
    • 实用软件:使用 Zabbix 监控主机
  • 2023-1112 FreeBSD 14.0
    • LinuxBoot:从 Linux 启动 FreeBSD
    • FreeBSD 容器镜像
    • 现在用 Webhook 触发我
    • 新的 Ports 提交者:oel Bodenmann (jbo@freebsd.org)
  • 2023-0910 Port 与软件包
    • 回忆录:与 Warner Losh(@imp)的访谈
    • 在你自己的仓库中定制 Poudriere 源
    • Wazuh 和 MITRE Caldera 在 FreeBSD Jail 中的使用
    • PEP 517
    • CCCamp 2023 旅行报告
  • 2023-0708 容器与云
    • 在 Firecracker 上的 FreeBSD
    • 使用 pot 和 nomad 管理 Jail
    • 会议报告:C 与 BSD 正如拉丁语与我们——一位神学家的旅程
    • 抒怀之旅:与 Doug Rabson 的访谈
    • 基于 Jail 的广告拦截教程
    • 我们收到的来信
  • 2023-0506 FreeBSD 三十周年纪念特刊
    • CheriBSD 近十多年的历程
    • AArch64:成为 FreeBSD 新的一级架构
    • 岁月如梭:我个人的时间线
    • 安装 FreeBSD 1.0:回顾 30 年前
    • ZFS 是如何进入 FreeBSD 的呢?
    • 我不是来自约克郡的,我保证!
    • 回忆录:采访 David Greenman Lawrence
    • FreeBSD 和早期的 Unix 社区
    • 早期的 FreeBSD 移植
    • FreeBSD 30 周年:成功的秘诀
    • FreeBSD 在日本:回忆之旅与今日之实
  • 2023-0304 嵌入式
    • CheriBSD port 和软件包
    • 让我们来试试 ChatGPT
    • GPU 直通
  • 2023-0102 构建 FreEBSD Web 服务器
    • ZFS 的原子 I/O 与 PostgreSQL
    • 虚拟实验室——BSD 编程研讨会
    • ZFS 简介
    • 会议报告:落基山庆祝女性计算机科学家
    • 进行中的工作/征求反馈:数据包批处理
    • 基金会与 FreeBSD 桌面
  • 2022-1112 可观测性和衡量标准
    • 在 FreeBSD 的 DDB 内核调试器中编写自定义命令
    • DTrace:老式跟踪系统的新扩展
    • 基于证书的 Icinga 监控
    • 活动监控脚本(activitymonitor.sh)
    • 实用 IPv6(第四部分)
    • EuroBSDCon 会议报道
    • 实用 Port:Prometheus 的安装与配置
    • 书评:《用火解决问题:管理老化的计算机系统(并为现代系统保驾护航)》Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)
  • 2022-0910 安全性
    • CARP 简介
    • 重构内核加密服务框架
    • PAM 小窍门
    • SSH 小窍门
    • 实用 IPv6(第三部分)
    • 书评:Understanding Software Dynamics(深入理解软件性能——一种动态视角)—— Richard L. Sites 著
    • 访谈:保障 FreeBSD 安全性
    • MCH 2022 会议报告
  • 2022-0708 科研、系统与 FreeBSD
    • 在 FreeBSD 上构建 Loom 框架
    • 教授本科生 Unix 课程
    • FreeBSD 入门研讨会
    • 实用 IPv6(第二部分)
    • 在 2022 年及以后推广 FreeBSD
    • 进行中的工作/征求反馈:Socket 缓冲区
    • FreeBSD 开发者峰会报告
    • 支持 Electromagnetic Field 2022
  • 2022-0506 灾难恢复
    • 使用 FreeBSD 构建高弹性的私有云
    • LLDB 14 —— FreeBSD 新调试器
    • 实用 IPv6(第一部分)
    • 利用 netdump(4) 进行事后内核调试
    • 进行中的工作/征求反馈:FreeBSD 启动性能
    • 实用 Port:在 OpenZFS 上设置 NFSv4 文件服务器
  • 2022-0304 ARM64 是一级架构
    • FreeBSD/ARM64 上的数据科学
    • Pinebook Pro 上的 FreeBSD
    • 嵌入式控制器的 ACPI 支持
    • 进行中的工作/征求反馈:Lumina 桌面征集开发人员
    • 实用 Port:如何设置 Apple 时间机器
  • 2022-0102 软件与系统管理
    • 为 FreeBSD Ports 做贡献
    • 使用 Git 贡献到 FreeBSD Ports
    • CBSD:第一部分——生产环境
    • 将 OpenBSD 的 pf syncookie 代码移植到 FreeBSD 的 pf
    • 进行中的工作/征求反馈:mkjail
    • 《编程智慧:编程鬼才的经验和思考》(The Kollected Kode Vicious)书评
    • 会议报告:EuroBSDCon 2021 我的第一次 EuroBSDCon:一位新组织者的视角
  • 2021-1112 存储
    • 开放通道 SSD
    • 构建 FreeBSD 社区
    • 与完美操作系统同行 27 年
    • 进行中的工作/征求反馈:OccamBSD
    • 通过 iSCSI 导入 ZFS ZIL——不要在工作中这样做——就像我做的那样
  • 2021-0910 FreeBSD 开发
    • FreeBSD 代码审查与 git-arc
    • 如何为 FreeBSD 实现简单的 USB 驱动程序
    • 内核开发技巧
    • 程序员编程杂谈
  • 2021-0708 桌面/无线网
    • 通往 FreeBSD 桌面的直线路径
    • FreeBSD 13 中的人机接口设备 (HID) 支持
    • Panfrost 驱动程序
    • 用 Git 更新 FreeBSD
    • FreeBSD 的新面孔
    • 想给你的桌面加点佐料?
  • 2021-0506 安全
    • 七种提升新安装 FreeBSD 安全性的方法
    • copyinout 框架
    • 使用 TLS 改善 NFS 安全性
    • Capsicum 案例研究:Got
    • 对 Jail 进行安全扫描
  • 2021-0304 FreeBSD 13.0
    • 展望未来
    • FreeBSD 13.0 工具链
    • FreeBSD 13.0 中有新加载器吗?
    • TCP Cubic 准备起飞
    • OpenZFS 中的 Zstandard 压缩
    • 会议报告:FreeBSD 供应商峰会
    • Git 不够吗?
  • 2021-0102 案例研究
    • Tarsnap 的 FreeBSD 集群
    • BALLY WULFF
    • Netflix Open Connect
    • FreeBSD 的新面孔
    • 写作学者的 FreeBSD
    • 在世界之巅
  • 2020-1112 工作流/持续集成(CI)
    • FreeBSD Git 快速入门
    • 使用 syzkaller 进行内核 Fuzzing
    • Mastering Vim Quickly 书评
    • 线上会议实用技巧
    • 在控制台上进行网络监控
  • 2020-0910 贡献与入门
    • 采访:Warner Losh,第 2 部分
    • 代码审查
    • 撰写良好的提交消息
    • 如何在不是程序员的情况下做出贡献——成为 FreeBSD 译者
    • 如何成为文档提交者
    • 谷歌编程之夏
    • 为 FreeBSD 期刊撰写文章
    • 你为什么使用 FreeBSD
    • FreeBSD 的新面孔
  • 2020-0708 基准测试/调优
    • FreeBSD Friday
    • 采访:Warner Losh,第 1 部分
    • 构建和运行开源社区
    • 在 FreeBSD 上轻松搭建我的世界(Minecraft)服务器
    • FreeBSD 的新面孔
  • 2020-0506 网络性能
    • 内核中的 TLS 卸载
    • 访谈:Michael W Lucas
    • FreeBSD 桌面发行版
    • 使用 Poudriere 进行 Port 批量管理
    • FreeBSD 的新面孔
由 GitBook 提供支持
LogoLogo

FreeBSD 中文社区(CFC) 2025

在本页
  • 加速克隆
  • 更进一步
  • 创建你的每日提交历史
  • 更改提交行为
  • 请签署你的签名
  • 修复小问题
  • 结论
在GitHub上编辑
导出为 PDF
  1. 2024-0304 开发工作流与集成

提升 Git 使用体验

上一页从零开始的 ZFS 镜像及 makefs -t zfs下一页FreeBSD 中的 RACK 栈和替代 TCP 栈

最后更新于1个月前

  • 作者:BENEDICT REUSCHLING

  • 原文链接:

版本控制历史悠久。掌握某种检索某个特定版本文件的方法,是我们旅程的开端。毕竟,这仅起了备份软件的作用。有些人把版本控制系统(VCS)这么用,但这仅是皮毛。VCS 真正有价值的地方,是能够审查文件的历史变更。与他人同用,可使重要项目文件与他们保持同步。在这种情况下,blame、diff、分支和合并等功能更为耦合。这些功能使在群体内值得共享的东西(文本、源代码、配置文件等)上进行协作成为可能。许多大量纳入上述文件的大型项目,如果缺乏基于 VCS 构建的复杂工具,将失去可维护性。版本控制系统来了又去,无论是商业供应商还是开源提供商。其中大都实现了用户所确立的基本功能,引入一套全新术语和复杂工具往往会被视为推广障碍。

在 FreeBSD 项目漫长的历史中,代码的每次更改都附有一个陈述性文本,即提交信息。对某些人来说,这似乎是件麻烦事。但事实上,在溯源过去的问题时,它很有帮助。为何在 15 年前做出了这项改变?是谁做出了这个修改,当次提交还包含了哪些别的文件,以及实际受影响的代码行是哪些?这些不仅是版本控制系统生成的 diff 相关联的问题,而且提交信息对于掌握如今正进行着的代码开发是种有价值的帮助。这通常贯通了过去与未来,因为 Unix 系统已经存在了很久,而且如今运行的硬件也是过去进行变更的人无法想象的。

由于 FreeBSD 存在了相当长的时间,保留这段丰富的历史极为重要。尤其是当必须转换到其他版本控制系统时。随着时间的推移,FreeBSD 曾经使用过 CVS(可以肯定,在早期也用过 RCS),然后迁移到了 Subversion,现在则使用着 git。每当进行这样的迁移,一个主要的目标就是保留所有的变更,及提交信息。

有时候不得不更换版本控制系统,因为供应商倒闭了,或者有比当前解决方案更吸引人的东西出现。至善者,善之敌。Git 如今已经成为版本控制的事实标准,即使它有些粗糙,学习曲线也十分陡峭。在我看来,作为 FreeBSD 项目用户、消费者以及 committer,重新熟悉 git,并让 git(而非其他)成为我工作的工具,让我花了一些时间。我可能仍无法完全掌握内部的全部工作原理,但幸运的是,我不必这样做。为 src 和 ports 工作的开发人员还会使用更多像分支、合并、Tag、cherry-pick、rebase 以及其他某些在文档存储库中不需要的功能。尽管如此,有时候在 ports 说明信息或改正手册页中的拼写错误时,还是需要像我这样,对这些概念至少有基本了解的人才能做事。

问题也还在于使用频率。如果在一年,某项功能我只用过一两次,就可能需要再次查阅,因为距上一次使用已经有一段时间了。克隆新树、拉取更新、进行更改、提交和推送这些基础操作,如果你经常进行,就会非常熟悉。我把它比作基本 vi 来使用。我可以打开文档,进行修改,保存并退出。但像 vi 这样强大的编辑器和其他类似工具提供的其他功能,可能会永远隐藏在我看不见的地方。同样,对于 git,它有很多功能藏于幕后,用户并不了解或者压根不需要。然而,一般对于这些高级功能有点知识和配置,即使对开发者,也极有帮助的,对用户亦如此。

FreeBSD 14 弃用了工具 portsnap——许多人曾用它来下载和更新 ports。手册和其他地方的说明现在要求用户直接从 git 检出 ports。当用户需要 src 时,亦如此。比如可能需要重新编译 VirtualBox 的内核模块。这些都是很好的使用案例,但有一个问题:由于上述悠久且丰富的历史,克隆 src 和 ports 需要很长时间。让我们看看,是否可以通过一些配置和工具来加速该过程。我们还将了解 git 提供的其他精彩功能,无论对普通用户张三还是开发者李四来说,都一样。

加速克隆

首先,在 FreeBSD 上安装 git,请运行 pkg install git。由于我们还没有 ports,况且现在也没有 portsnap 了。可能会在那些无法访问 FreeBSD 镜像站的系统上,造成先有鸡,还是先有蛋的悖论。在你的局域网中,poudriere 机器可能是解决方案,或者在不同的机器上下载文件,复制二进制文件,然后用 pkg install ./<软件包名> 进行安装。

请注意,git port 本身包含了丰富的可选配置参数。由于我们刚开始,可以暂时无视这些选项,并在经验丰富时重新审视它们。如果你发现某些有用的东西,请考虑写成博客或为 FreeBSD 杂志写篇文章。毕竟,独木难支。

如 git 可用,我们可以返回上面的使用案例:下载 Ports。FreeBSD 手册第 4 章告诉我们,我们可以下载 HEAD 分支(最新最全的)或者稍微保守一点,下载季度分支。无论我们选择哪个,我们都会看到一个非常熟悉的命令 git clone。这都很好,但是下载上述全部文件和目录需要很长时间。让我们看看写这篇文章时的季度分支。我将使用 time(1) 命令来测量下载时间。

$ time git clone https://git.FreeBSD.org/ports.git -b 2024Q1 /usr/ports
Cloning into '/usr/ports'...
remote: Enumerating objects: 6125935, done.
remote: Counting objects: 100% (960/960), done.
remote: Compressing objects: 100% (142/142), done.
Receiving objects: 100% (6125935/6125935), 1.20 GiB | 36.28 MiB/s, done.
remote: Total 6125935 (delta 925), reused 833 (delta 818), pack-reused 6124975
Resolving deltas: 100% (3700108/3700108), done.
Updating files: 100% (158490/158490), done.
git clone https://git.FreeBSD.org/ports.git /usr/ports
0.00s user 0.03s system 0% cpu 3:34.48 total

与带宽无关,对我而言,3 分 34 秒太长了。我们可以让他更快。由于我们不需要所有的历史,仅需最新版本的文件,若使用 --depth-1 进行浅克隆会快得多。

time git clone --depth=1 https://git.FreeBSD.org/ports.git /usr/ports
Cloning into '/usr/ports'...
remote: Enumerating objects: 194509, done.
remote: Counting objects: 100% (194509/194509), done.
remote: Compressing objects: 100% (182218/182218), done.
remote: Total 194509 (delta 11904), reused 120301 (delta 5787), pack-reused 0
Receiving objects: 100% (194509/194509), 85.40 MiB | 10.48 MiB/s, done.
Resolving deltas: 100% (11904/11904), done.
Updating files: 100% (158490/158490), done.
git clone --depth=1 https://git.FreeBSD.org/ports.git /usr/ports
0.01s user 0.01s system 0% cpu 28.709 total

确实快得多(29 秒),我得到了我想要的东西。如果我需要完整的历史记录:因为我在解决一个 bug,那么我可以使用一个过滤函数首先获取整个提交历史,但不包括历史记录。后者可能作为一个单独的步骤出现。我希望减少下载时间,因此让我们尝试这个:

time git clone --filter=blob:none https://git.FreeBSD.org/ports.git /usr/ports
Cloning into '/usr/ports'...
remote: Enumerating objects: 3706789, done.
remote: Counting objects: 100% (794/794), done.
remote: Compressing objects: 100% (82/82), done.
remote: Total 3706789 (delta 771), reused 721 (delta 712), pack-reused 3705995
Receiving objects: 100% (3706789/3706789), 704.87 MiB | 48.79 MiB/s, done.
Resolving deltas: 100% (2043361/2043361), done.
remote: Enumerating objects: 152073, done.
remote: Counting objects: 100% (63494/63494), done.
remote: Compressing objects: 100% (61224/61224), done.
remote: Total 152073 (delta 7810), reused 2276 (delta 2270), pack-reused 88579
Receiving objects: 100% (152073/152073), 78.98 MiB | 10.93 MiB/s, done.
Resolving deltas: 100% (11301/11301), done.
Updating files: 100% (158490/158490), done.
git clone --filter=blob:none https://git.FreeBSD.org/ports.git /usr/ports
0.00s user 0.03s system 0% cpu 1:51.29 total

Git 将工作分为两部分:首先,所有的 blob(这里是文件)被过滤掉,仅获取历史。在第二步,获取 blob。快于完全克隆,但慢于浅拷贝。检索的大小也有所不同,这有助于加快速度。在常规克隆中,我们下载了 1.20 GB。无 blob 克隆的两步过程让 git 先下载了 704.87 MB 的历史,然后是 78.98 MB。但有好处也有缺点:当我找到 bug 并想知道这是什么时引入的时候, git blame 操作需要首先从服务器获取这些修订版版。如果我在路上,却没有网络访问,我就有点倒霉了。完全克隆能够给我这些信息,因为它已检索了所有的历史。再次强调,对于对获取文件本身感兴趣的非开发人员来说,这无所谓,好处在于下载时间更短。

更进一步

想象一下,如果你正在处理源代码中的 man 页。下载完整的内核、用户空间、工具和其中的所有内容,对于初次克隆来说是相当沉重的工作。如果你只是偶尔处理这些 man 页会怎样呢?毫无疑问,他人会对其进行更改,我们需要知晓这些更改。如果我们的系统能够帮我们获取这些更改,使得我们本地的副本不会距离源代码树顶端太远那不是很好吗?git 中的 scalar 工具解决了这个问题:快速下载一个大型存储库并定期从上游检索更改。这将把本地克隆置于维护模式,这个功能的另一个花俏的说法就是这个。以下是如何使用它的方法:用 scalar 替换 git ,命令的其余部分则保持不变。

time scalar clone https://git.FreeBSD.org/src.git /usr/src
Initialized empty Git repository in /usr/src/src/src/.git/
remote: Enumerating objects: 2386494, done.
remote: Counting objects: 100% (258756/258756), done.
remote: Compressing objects: 100% (16493/16493), done.
remote: Total 2386494 (delta 253705), reused 244654 (delta 242263), pack-reused 2127738
warning: fetch normally indicates which branches had a forced update,
but that check has been disabled; to re-enable, use '--show-forced-updates'
flag or run 'git config fetch.showForcedUpdates true'
warning: fetch normally indicates which branches had a forced update,
but that check has been disabled; to re-enable, use '--show-forced-updates'
flag or run 'git config fetch.showForcedUpdates true'
remote: Enumerating objects: 20, done.
remote: Counting objects: 100% (17/17), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 20 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (20/20), 196.11 KiB | 16.34 MiB/s, done.
warning: fetch normally indicates which branches had a forced update,
but that check has been disabled; to re-enable, use '--show-forced-updates'
flag or run 'git config fetch.showForcedUpdates true'
branch 'main' set up to track 'origin/main'.
Switched to a new branch 'main'
Your branch is up to date with 'origin/main'.
crontab: no crontab for root
scalar clone https://git.FreeBSD.org/src.git
0.01s user 0.00s system 0% cpu 31.971 total

现在先无视那些警告,进程仍会完成。这里有关于定期获取更新的 crontab(1) 的一些内容。要将现有存储库转换为使用 scalar,不用再次克隆:在存储库的根目录中运行 scalar register,它将会将本地副本转换并使用它。完美!scalar 命令会设定一个 crontab 条目。如果你没有用户特定的 crontab(就像我这里为 root 用户设置的那样),那么课运行 crontab -e 来设置它。如果一切顺利,git 将添加一个 scalar 运行的条目:

# BEGIN GIT MAINTENANCE SCHEDULE
# The following schedule was created by Git
# Any edits made in this region might be
# replaced in the future by a Git command.

29 1-23 * * * “/usr/local/libexec/git-core/git” --exec-path=”/usr/local/libexec/git-core” for-each-repo --config=maintenance.repo maintenance run --schedule=hourly
29 0 * * 1-6 “/usr/local/libexec/git-core/git” --exec-path=”/usr/local/libexec/git-core” for-each-repo --config=maintenance.repo maintenance run --schedule=daily
29 0 * * 0 “/usr/local/libexec/git-core/git” --exec-path=”/usr/local/libexec/git-core” for-each-repo --config=maintenance.repo maintenance run --schedule=weekly
# END GIT MAINTENANCE SCHEDULE

可调整这些条目以符合你自己的需求,或保持不变。如果机器设置了正确的邮件设置,当运行 cron 作业时,你将收到包含获取的修订版本的消息。scalar 克隆和相关的维护作业所做的另一件事是将一个条目添加到你的 git 配置文件中,命名应为 .gitconfig。

[scalar]
repo = /usr/src
[maintenance]
repo = /usr/src

这将直接将我们带入 git 的配置文件中。

创建你的每日提交历史

随时间推移,你可能会在多个存储库上进行工作:一个用于工作,另一个用于私人项目——为你喜爱的开源项目做贡献。这些克隆存储库的配置可能不同。例如,你可能在提交时使用你的企业电子邮件来标识自己,但在提交到私人项目时可能不合适甚至不允许。因此,我们可以在存储库的一部分设有特定于项目的 git/config 和一个适用于你正在工作的所有存储库的全局 git/config。

全局 .gitconfig 位于你的主目录中。你可以直接编辑该文件(如果你知道你在做什么),或者使用 git 来管理文件的内容并设置适当的值。后者使用这种语法:

git config --global NAME VALUE

例如,要注册我的姓名以进行提交,我运行:

git config --global user.name Benedict Reuschling

这会在 .gitconfig 中出现这样的条目:

[user]
        name = Benedict Reuschling

你可以看到,像用户(电子邮件在其中,你最好也设置一下)这样的条目有括号中的类别。其他的是 commit,diff 和 branch。

更改提交行为

放下火把和草叉,我不喜欢用 nano 来写我的提交消息。要定义你自己的编辑器,执行这个命令:

git config --global core.editor nvim

基本上,你总是想把他设置为全局选项。在项目的 .git/config 中引入这个配置并将其提交,将导致生产效率急剧下降,因为其他贡献者将同你开始一场神圣的编辑器之战,导致仓库中充斥着试图将其更改为他们自己个人喜欢的编辑器的修改。在那天,讽刺你的老板永远地关上了你身后的公司大门,你会记起他的最后一句话是——“你真是个大聪明!”。

还有其他配置设置会(更积极地)影响你的提交体验。这里列出了较多选项,但默认设置很好。稍调一些选项可以在一定程度上改善你的 git 体验,并可能消除一些个人困扰(请参阅下文)。有关详细信息,请参阅 git-config(1)。

如何为复杂和常用但繁琐的命令定义别名?这就是别名部分派上用场的地方。我已经定义了这些别名:

[alias]
    last = last -1 HEAD
    g = log --graph --all --pretty=format:'%Cred%h -%C(yellow)%d%Creset %s %Cgreen(%ci) %C(bold blue)<%an (%ae)>'

类似地,当查看日志时,我希望至少看到这些字段:提交、作者、作者进行更改的日期,以及提交及其日期。通过查看 git-log(1) 并找出这个选项被称为更全面实现:

git config --global format.pretty fuller

在我的代码库中,我可以运行 git last 等同于运行命令 git last -1 HEAD。想想现在只需敲几下键盘,就能看到彩色等花哨的效果,我就更喜欢 git lg 命令了。你自己试试看,回头再谢我吧。

当我进行实际提交时,我希望看到到底提交了什么。Git 在提交消息的文本区域下方显示头修订版本与我的更改之间的差异,使用此设置:

git config --global commit.verbose true

请签署你的签名

谈到提交,为什么不给你的提交进行签名呢?"嗯,GPG/PGP 的设置太复杂可能是一个回答。有一个解决方法:改用 SSH。在 GitHub 等服务或你的公司(或私有)的 GitLab 实例上,你已经上传了一个用于通过 SSH 拉取存储库的公钥。使用相同的密钥对提交进行签名为你的更改增加了额外的信誉。在这些平台上提交旁边经常有一个“signed(已签名)”图标或标签表示信誉。设置非常简单,我想知道为什么到现在还不是默认设置。下面是具体方法:

git config --global gpg.format ssh
git config --global user.signingKey ‘ssh-ed25519 AAAAC3(...)34rve user@host’

是否应在所有地方使用相同的 SSH 密钥,目前存在争议。如果不希望,请从上面的最后一行中删除参数 --global ,并为每个存储库单独更改其密钥。

现在可以这样提交:

git commit -S

要始终签名,请将其设为默认:

git config --global commit.gpgsign true

但这是什么呢?当运行 git show --show-signature 时,没显示我们的签名,而是显示错误消息。不太行!幸运的是,消息还告诉我们需要更改的内容:gpg.ssh.allowedSignersFile 就是我们需要改变的选项。

这个 Git 报错是因为 SSH 没有建立一个由其他人签署密钥的信任网络。故,我们需要告诉 git 我们信任哪些密钥。由单独的文件,包含了所有信任的 SSH 签名。因为我们是有条理的人,让我们把这个文件放在 ~/.config/git/allowed_signers 下(如果路径不存在则创建之)。

allowed_signers 的内容如下:

email ssh-ed25519 ssh_public_key comment

目光敏锐的人会认出它与 ssh-keygen(1) 使用的格式相同。我们至少需要信任自己的 SSH 密钥,所以将其放在这里。重复此步骤,适用于你圈子中的所有其他为仓库做贡献并签署其提交的人。为了教会 git 如何处理这个文件,添加另一个配置选项(正是之前错误消息的提及那个)。

git config --global gpg.ssh.allowedSignersFile “~/.config/git/allowed_signers”

重试命令 git show --show-signature(并为其创建一个别名),看看错误消息是否被 git 签名替换。

修复小问题

更新本地副本建议运行 git pull --ff-only,这是默认行为。如果经常忘记添加参数,则可以将其设置为默认拉取行为,如下所示:

git config --global pull.ff only

当然,你也可以为其创建别名。这是一项“一次但永久性”的设置。

在查看 diff 时,我一直在想为什么 git 使用 a/ 和 b/ 来区分文件。我不需要这些,文件名已经可以代表它们自己。我发现可以通过以下选项禁用此行为:

git config --global diff.noprefix true

说到 diff,我想看到我更改的附近最少 5 行内容。这是一个个人偏好,但任何人都可以使用此选项设置自己喜欢的方式:

git config --global diff.context 5

在像 FreeBSD 这样的国际项目上的工作,教会了我日期可以有多种书写格式。git 使用的默认显示方式是 Fri Mar 01 12:34:56 2024。这没有什么问题,但我习惯于这个方式:2024-03-01 12:34:56。这个参数将日期设置为我喜欢的样子:

git config --global log.date iso

我发现,另外一件奇怪的事情是 git 在运行 git branch 时列出分支的顺序。我希望最近提交的分支显示在顶部,而不是什么随机顺序。要更改这个设置,我的 .gitconfig 加入了这个内容:

git config --global branch.sort -committerdate

现在我可以精确地看到哪个分支接收了最近的更改。是时候合并了!

结论

随着时间的推移,我的配置不断增加,因为我大概发现了其他有用的选项。Git 配置十分灵活。默认设置对大多数人来说都很好,而且也很容易修改。这篇文章应该可以帮助你开始编写自己的配置,可在使用 git 时减少某些磨合问题。

参考资料:


BENEDICT REUSCHLING 是 FreeBSD 项目的文档提交者和文档工程团队成员。他曾任两届 FreeBSD 核心团队成员。他在德国达姆施塔特应用技术大学管理着一个大数据集群。他还为本科生教授着“Unix 开发者”这门课。Benedict 是 bsdnow.tv 每周播客的主持人。

https://freebsdfoundation.org/our-work/journal/browser-based-edition/development-workflow-and-ci/enhance-your-git-experience/
https://blog.gitbutler.com/git-tips-and-tricks/
https://jvns.ca/blog/2024/02/16/popular-git-config-options/
https://blog.dbrgn.ch/2021/11/16/git-ssh-signatures/