Skip to content

Git 最近的一些有用的更新

· 8 min
TL;DR

本文精选介绍了 Git 2.40.0 以后版本中的六项实用功能更新。文章详细解析了 reftable 新存储格式如何高效处理大量引用;SHA-1 与 SHA-256 算法的兼容措施;git diff 显示格式的自定义配置;commit 信息注释格式的个性化设置;配置时添加注释的新功能;以及 git revert 命令输出信息的改进。每个特性都配有实际命令示例和使用场景分析,帮助开发者利用这些新功能提升 Git 使用体验和工作效率。

1. reftable 的初步支持#

传统的 git 仓库,本地或远程分支以及 tag 的信息都记录在 .git/refs/heads/.git/refs/remotes/.git/refs/tags/ 目录下,里面每个文件包含它们指向的对象的 sha 值,它们就叫做引用 (reference)。当我们的 git 仓库存在大量分支或 tag 时,意味着仓库里包含大量引用,如果引用被打包成一个单一的大的引用包 (.packed_refs) 就变得难以维护 (如在更新或重写时会消耗很多 IO);同时,如果有大量未被打包的 “松散引用” 也会导致磁盘负担 (如查询变慢,或者占用磁盘 inode),这是传统的 git 引用的存储方式的弊端。现在 (2.45.0 开始) git 引入了新的引用存储格式,即 reftable。reftable 原是为 Gerrit 项目设计的一种二进制存储引用的方式,具备常数时间的引用查询、常数时间的引用对象校验、节省存储空间等优点。

如何在 git 仓库中使用该特性:

Terminal window
# 在新仓库中,使用 git-init 初始化
$ git init --ref-format=reftable /path/to/repo
# git commit 之后,可以看到.git/ 目录多了 reftable/ 目录
$ ls -l .git/reftable/
0x000000000001-0x000000000002-ca426570.ref
tables.list
$ cat .git/reftable/tables.list
0x000000000001-0x000000000002-ca426570.ref
# 0x000000000001-0x000000000002-ca426570.ref 文件内容是二进制的,所以即使查看也是乱码

2. SHA-1, SHA-256 的初步相互兼容支持#

注:目前还是实验性质,如果本地仓库是使用 SHA-256 算法,是无法推送到远程仓库的。

我们知道 git 仓库一直是使用 sha1 算法对 git 仓库中的各种对象,包括 commit, tag, tree, blob 等计算其 hash 值来标识它们的。但是由于 sha-1 不再绝对安全,所以 git 社区也在考虑使用更安全的 sha256 算法。目前 (2.45.0 开始) 已实现初步的功能.

Terminal window
在初始化一个新仓库时,使用 --object-format 指定
$ git init --object-format=sha256 /path/to/repo
Initialized empty Git repository in /path/to/repo/.git
# 设置兼容 sha1
$ cd /path/to/repo
$ git config extensions.compatObjectFormat sha1
# 向仓库中添加文件并提交后
$ git rev-parse HEAD | git cat-file --batch
74dcba4f8f941a65a44fdd92f0bd6a093ad78960710ac32dbd4c032df66fe5c6 commit 202
tree ace45d916e870ce0fadbb8fc579218d01361da4159d1e2b5949f176b1f743280
author A U Thor <author@example.com> 1713990043 -0400
committer C O Mitter <committer@example.com> 1713990043 -0400
initial commit
# 由于设置了兼容配置,所以也可以查看原来的格式:
$ git rev-parse --output-object-format=sha1 HEAD
2a4f4a2182686157a2dc887c46693c988c912533
$ git rev-parse --output-object-format=sha1 HEAD | git cat-file --batch
2a4f4a2182686157a2dc887c46693c988c912533 commit 178
tree 7dd49419807b37a3afd2f040891a64d69abb8df1
author A U Thor <author@example.com> 1713990043 -0400
committer C O Mitter <committer@example.com> 1713990043 -0400
initial commit

3. git diff 显示格式的设置#

在使用 git diff 或 git show 查看文件的修改差异时,在新旧文件名前的前缀都是 a/、b/,如:

 $ git diff HEAD^ -- GIT-VERSION-GEN
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index dabd2b5b89..c92f98b3db 100755
--- a/GIT-VERSION-GEN   <------ 这里
+++ b/GIT-VERSION-GEN   <------
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.45.0-rc0
+DEF_VER=v2.45.0-rc1

现在 (2.45.0 开始) 可以修改这个前缀,比如修改为:before/, after/, 更有用的方式是修改为:./,这样就成了一个有效的文件链接,可以直接点击跳转。

Terminal window
$ git config diff.srcPrefix "./"
$ git config diff.dstPrefix "./"
# 不要忘了同时修改 srcPrefix, dstPrefix
 $ git diff HEAD^ -- GIT-VERSION-GEN
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index dabd2b5b89..c92f98b3db 100755
--- ./GIT-VERSION-GEN   <------ 配置后的显示
+++ ./GIT-VERSION-GEN   <------
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.45.0-rc0
+DEF_VER=v2.45.0-rc1

4. 更改编写 commit 信息时的注释格式#

我们知道使用 git add 添加文件之后再直接执行 git commit 命令会进入交互式界面,提示我们编写 commit message, 默认显示如下:

Terminal window
Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Changes to be committed:
#       modified:   README
#

根据上面的提示信息,以单字节 "#" 开头的都是注释信息将会被忽略。而最新版本的 git (2.45.0 开始) 可以定制化这个注释的格式,设置多字节的字符,配置方式如下:

Terminal window
$ git config core.commentString "//"

注:在我的 Windows 上,这里设置的 "//" 会变为 "/", 所以要想双斜线,需要配置为 "///",还没在其他环境中验证,不知道是不是 bug。

这样配置好处是可以使用自己喜欢的注释方式,更实用的是,当不使用 "#" 作为注释符时,可以直接在 commit message 开头使用 #1234 这类特殊的标识方式,它可以代表 issue 号或者 PR 号,是不是更方便了。

5. 修改配置时,进行注释#

有时候我们配置了很多配置项,但是忘了加注释,这会妨碍阅读。虽然在之后可以手动修改 gitconfig 文件,但是仍不够方便。现在 (2.45.0 开始) 可以在修改配置同时追加注释。

Terminal window
$ git config --comment 'to show the merge base' merge.conflictStyle diff3
$ tail -n 2 .git/config
[merge]
conflictStyle = diff3 # to show the merge base

6. git revert 的修改信息改进#

在 git-2.43.0 之前,对同一个提交多次进行 git revert 的效果如下:

Terminal window
$ git revert --no-edit HEAD
$ git revert --no-edit HEAD
$ git revert --no-edit HEAD
$ git log --oneline
eaf9b18 (HEAD -> master) Revert "Revert "Revert "second commit"""
79484d1 Revert "Revert "second commit""
48f8ac7 Revert "second commit"
e75a561 second commit
0eaa862 init commit

以上是进行了三次 revert 的效果。 从 git-2.43.0 开始,同样的操作之后,效果如下:

Terminal window
$ git log --oneline
f0b1ba1 (HEAD -> main) Revert "Reapply "second commit""
e0f604b Reapply "second commit"
7fc1641 Revert "second commit"
7b82442 second commit
66ae27c init commit

可读性更好了。

以上是从 git-2.40.0 以来发布的 git 版本中发现的一些有用和有趣的更新。当然,截止到当前的 2.45.2,这期间还有很多的性能优化以及安全漏洞问题更新并没有在这里涉及,感兴趣的话可以去 官方博客 查看。