Git 2.54 亮点速览

Lobsters Hottest 工具

摘要

Git 2.54 带来全新的实验性 `git history` 命令,可在不碰工作区的情况下重写或拆分提交,另有 137 位贡献者带来的其他改进。

<p><a href="https://lobste.rs/s/ojh2aq/highlights_from_git_2_54">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/04/21 18:42

# Git 2.54 亮点 来源:https://github.blog/open-source/git/highlights-from-git-2-54/ 开源 Git 项目刚刚发布了 Git 2.54(https://lore.kernel.org/git/TODO),包含 137 位贡献者的功能与缺陷修复,其中 66 位首次贡献。上一次我们聊 Git 新特性还是 2.52 发布时(https://github.blog/open-source/git/highlights-from-git-2-52/)。为庆祝新版,GitHub 带你速览自那以来最值得关注的变化。 > 💡 由于上一篇覆盖的是 Git 2.52,本文将同时汇总 2.53 与 2.54 的亮点。 ## 用 `git history` 重写历史 Git 向来提供多种重写历史的工具,最出名的 `git rebase -i`(https://git-scm.com/docs/git-rebase/2.54.0)几乎无所不能:重排、压缩、编辑、删除提交。但强大伴随复杂——交互式变基要处理提交区间、中途更新工作区与索引,还可能留下冲突待解。如果只是想把三条前的提交信息改个错别字,或把一个提交拆成两个,就显得“杀鸡用牛刀”。 Git 2.54 带来全新的实验命令,专为这类轻量场景设计:`git history`。目前支持两种操作:`reword` 与 `split`。 - `git history reword <提交>` 打开编辑器让你原地修改提交信息,并自动更新所有基于该提交的分支。不同于 `git rebase`,它不动工作区与索引,甚至能在裸库执行。 - `git history split <提交>` 以交互方式把指定提交拆成两个:通过选择哪些 hunk 组成新父提交。界面类似 `git add -p`: ``` $ git history split HEAD diff --git a/bar b/bar new file mode 100644 index 0000000..50810a5 --- /dev/null +++ b/bar @@ -0,0 +1 @@ +bar (1/1) Stage addition [y,n,q,a,d,p,?]? y ``` 选完后 Git 会新建一个包含所选变更的父提交,原提交保留剩余内容,并重写下游分支。 注意:该命令暂不支持含合并提交的历史,也拒绝任何可能产生冲突的操作。设计上,`git history` 只做定向、非交互的小修小补,而非 `git rebase -i` 那种大开大合。它底层复用了本次一并抽离成库的 `git replay` 机制,因此无需触碰工作区,方便脚本与自动化使用。接口仍属实验性质,未来可能微调。现在就可安装 Git 2.54 体验 `git history reword` 与 `git history split`。 [来源 1](https://github.com/git/git/compare/3e0db84c88c57e70ac8be8c196dfa92c5d656fbc...d205234cb05a5e330c0f7f5b3ea764533a74d69e) [来源 2](https://github.com/git/git/compare/aa95f87c740011f7d21555c5ad7f0870faf4b5c8...1278a26544e81dddf564fd7730890a7e023ed367) [来源 3](https://github.com/git/git/compare/2eec0f51156ea872174bbd08f355155f381a568e...d1f33c753de68f63c945c3213f439081ed11c27b) [来源 4](https://github.com/git/git/compare/dd33e738a469cb7841a4a6132bdce1809d0772aa...d563ecec2845467880f5742e178a9723afef495a) [来源 5](https://github.com/git/git/compare/f1743ad69a492d1ca3773bfdddf7f5ffd278c19b...26b9946dd756a2efc29f898e53327676a22adc3e) ## 基于配置的钩子 如果想把某个 Git 钩子(https://git-scm.com/docs/githooks)共享到多个仓库,以往只能借助第三方钩子管理器,或手动把脚本软链到各仓库 `$GIT_DIR/hooks`。因为传统上钩子只能是 `.git/hooks` 里的可执行文件(或由 `core.hooksPath` 指定),想给所有仓库加一条提交前 lint,就得逐个复制,既麻烦又容易遗漏。若把 `core.hooksPath` 指向公共目录,又会让所有仓库共用同一套钩子,无法按需组合。 Git 2.54 支持直接在配置文件里声明钩子。不必再放 `.git/hooks/pre-commit`,可以写: ``` [hook "linter"] event = pre-commit command = ~/bin/linter --cpp20 ``` `hook.<name>.command` 指定要运行的命令,`hook.<name>.event` 指定触发时机。配置可放在用户级 `~/.gitconfig`、系统级 `/etc/gitconfig` 或仓库自身配置,实现“一次定义,到处生效”。更棒的是,同一事件可绑定多个钩子: ``` [hook "linter"] event = pre-commit command = ~/bin/linter --cpp20 [hook "no-leaks"] event = pre-commit command = ~/bin/leak-detector ``` Git 按配置顺序执行。传统 `$GIT_DIR/hooks` 脚本仍有效,且最后执行,现有钩子不受影响。用 `git hook list` 可查看当前生效的钩子及其来源: ``` $ git hook list pre-commit global linter ~/bin/linter --cpp20 local no-leaks ~/bin/leak-detector ``` 单个钩子可通过 `hook.<name>.enabled = false` 禁用,无需删除配置,方便在系统级配置中统一提供、个别仓库按需关闭。顺带,Git 内部钩子调用路径已现代化,众多内置钩子(如 `pre-push`、`post-rewrite` 及各类 `receive-pack` 钩子)都迁移到新的 hook API,一并享受配置化红利。 [来源 1](https://github.com/git/git/compare/4aa72ea1f64e8ddcd1865c76b24591c0916c0b5d...005f3fbe07a20dd5f7dea57f6f46cd797387e56a) [来源 2](https://github.com/git/git/compare/9a8aebae972de22ecd5adb92fec9d77147949c8a...ec1c4d974ac74afb4f0574d29f7bbb30c1c46431) [来源 3](https://github.com/git/git/compare/4e5821732e684f21a35288d8e67f453ca2595083...5c58dbc887a1f3530cb29c995f63675beebb22e9) ## 默认启用几何重打包 老读者可能还记得我们在 Git 2.52 中介绍的 `git maintenance` 新增 `geometric` 策略(https://github.blog/open-source/git/highlights-from-git-2-52/#advanced-repository-maintenance-strategies)。该策略通过检查仓库中的 packfile,看是否能按对象数量构成等比数列,若能就执行几何重打包,避免全量垃圾回收。2.52 时需在 `maintenance.strategy` 手动开启;2.54 起,手动执行 `git maintenance run` 默认采用几何策略。也就是说,现在什么都不用配,Git 就会用更轻量的方式维护仓库:只有在必要时才增量合并 pack,实在无法合并时才回退到传统 `gc`。期间同步保持 commit-graph、reflog 等辅助数据结构最新。若你已手动设置 `maintenance.strategy = geometric`,行为不变;若从未设置(或依赖旧默认 `gc`),升级后即可自动享受几何重打包的好处。仍偏爱 `gc` 的用户可显式写 `maintenance.strategy = gc`。 [来源](https://github.com/git/git/compare/1ebfc2171310ed5ca2bcd8c1255d45f03e56dda7...452b12c2e0fe7a18f9487f8a090ce46bef207177) ## 冰山一角…… 看完大块头更新,再快速浏览其他新功能: - `git add -p` 交互式块选择器小幅升级:用 `J`/`K` 在块间跳转时,会显示之前已接受或跳过的标记,避免重复审阅。新增 `--no-auto-advance` 标志,处理完一个文件的所有块后不再自动切到下一文件,可用 `<`/`>` 手动游走,方便整体复查后再提交。[来源 1](https://github.com/git/git/compare/2b53e8b3ee7f143af785e2a39ce4e1614ff6c66e...8cafc305e22a59efb92472d4132616e24d3184c6)、[来源 2](https://github.com/git/git/compare/f19f1b6cf37d22cf317b5c3b52a11eede1abe267...417b181f99ce53f50dea6541430cfe1f1f359a6a) - 实验命令 `git replay` 继续成熟:默认原子更新引用(不再打印 `update-ref` 到 stdout);新增 `--revert` 模式可反向回滚一段提交;支持丢弃回放过程中变空的提交;可一直回放到根提交。[来源 1](https://github.com/git/git/compare/7bf3785d0973d229fa21a76122c7e4735a2b1ffb...0ee71f4bd035db61342c2c5a25984e4545347c11)、[来源 2](https://github.com/git/git/compare/05ddb9ee8a4c619fbb0e7309fe291bff5cd7c987...2760ee49834953c0860fa5d7983a6af4d27cb6a9)、[来源 3](https://github.com/git/git/compare/03311dca7f91f69e9e0c532fce1c1e3c0a9fa34d...e8b79a96ebaa2113391d14bfcdabe239f6ff8611)、[来源 4](https://github.com/git/git/compare/d8c553bbed21761a8af3fa40a20518e210e78a0d...23d83f8ddbef9adcb87671358b473e55cf90c90b) - Git HTTP 传输现在能处理 HTTP 429 “Too Many Requests”。过去遇到 429 直接报错;现在会按服务器 `Retry-After` 头等待,或用新配置 `http.retryAfter` 退避,同时可用 `http.maxRetries` 和 `http.maxRetryTime` 控制重试次数与总时长。[来源](https://github.com/git/git/compare/270e10ad6dda3379ea0da7efd11e4fbf2cd7a325...640657ffd06999ec1ec3b1d030b7f5aac6b7f57b) - `git log -L` 追踪文件内行级历史时,过去走专用输出通道,与 `-S`/`-G` 等“镐头”选项不兼容。本版将其接入标准 diff 管道,首次支持 patch 格式与内容搜索联用。例如只想看 `strbuf_addstr()` 里新增或删除 `len` 的提交: ``` $ git log -L :strbuf_addstr:strbuf.c -S len --oneline -1 a70f8f19ad2 strbuf: introduce strbuf_addstrings() to repeatedly add a string diff --git a/strbuf.c b/strbuf.c --- a/strbuf.c +++ b/strbuf.c @@ -316,0 +316,9 @@ +void strbuf_addstrings(struct strbuf *sb, const char *s, size_t n) +{ + size_t len = strlen(s); + + strbuf_grow(sb, st_mult(len, n)); + for (size_t i = 0; i < n; i++) + strbuf_add(sb, s, len); +} ``` 此前 `-S`、`-G`、`--word-diff`、`--color-moved` 等会被静默忽略,现在与 `-L` 自然组合:`-L` 限定范围,`-S` 再过滤内容。[来源](https://github.com/git/git/compare/fb5516997ef3f882d8e53ce70ba6077533683621...512536a09ea2964e93226f219898ee0a09d85a70) - 增量多包索引(MIDX)在 2.47 首次亮相、2.50 加入可达位图后,本版新增压缩(compaction)功能:把较小的 MIDX 层连同其位图合并,控制链条长度,为长期积累大量层的老仓库铺平道路。[来源](https://github.com/git/git/compare/ce74208c2fa13943fffa58f168ac27a76d0eb789...d54da84bd9de09fc339accff553f1fc8a5539154) - `git status` 新增 `status.compareBranches` 配置,默认只比较当前分支与其上游;现在可让 status 同时对比 push 远程,或两者都比: ``` [status] compareBranches = @{upstream} @{push} ``` 适用于三角工作流(从一处拉取、往另一处推送,如先 fork 再 PR)。[来源](https://github.com/git/git/compare/d79fff4a11a5...68791d7506aa) - 想给一串提交批量添加尾注?不必手动逐条修改,可自动化: ``` git rebase -x 'git commit --amend --no-edit --trailer="Reviewed-by: A U Thor ```

相似文章

Git 由什么构成?(2022)

Lobsters Hottest

深入教程,解释 Git 的内部结构,包括对象、哈希以及 Git 如何存储数据,并提供 Go 和 shell 命令示例。

离开 Magit 后的 Emacs

Lobsters Hottest

作者讲述了他们离开 Emacs 的 Magit Git 界面,转而采用 VC-mode 和自定义 Git 脚本等替代方案的经历,重点介绍了其中的调整和所学到的经验教训。

Show HN:面向AI代理的Git

Hacker News Top

re_gent 是一个开源的版本控制系统,专为AI代理活动设计,记录每一次工具调用及其相关提示,使开发者能够审查和回滚代理的变更。

Show HN: Codiff,本地差异审查工具

Hacker News Top

Codiff 是一款轻量级本地 diff 查看器,用于审查 Git 暂存和未暂存的更改,支持基于 LLM 的逐步讲解和内联审查评论。

@laogui: 经过几天使用,我可以毫不夸张地说:Rebased 就是目前最强的 Git 图形化客户端。 用过 JetBrains 系列 IDE 的朋友都知道,它的 Git 功能体验非常好——尤其是 Diff 功能。但这几年 JetBrains 在 AI…

X AI KOLs Timeline

Rebased 是一款基于 JetBrains IntelliJ 社区版构建的开源 Git 图形化客户端,砍掉了所有语言相关功能,只保留并优化了 Git 工具,提供了顶级的 Diff、Review、交互式 Rebase 和冲突解决体验,免费使用且零学习成本。