git-absorb:自动的git commit --fixup
摘要
git-absorb自动为暂存的更改创建fixup提交,实现了与hg absorb类似的功能。它与git的autosquash集成,简化了应用代码审查反馈的过程,无需手动查找提交的SHA。
查看缓存全文
缓存时间: 2026/07/14 10:16
tummychow/git-absorb
源地址:https://github.com/tummychow/git-absorb
git absorb
这是 Facebook 的 hg absorb(https://www.mercurial-scm.org/repo/hg/rev/5111d11b8719)的一个移植版本,我最早是在 mozilla.dev.version-control(https://groups.google.com/forum/#!msg/mozilla.dev.version-control/nh4fITFlEMk/ZNXgnAzxAQAJ)上看到相关介绍的:
- Facebook 演示了
hg absorb,这大概是我多年来见过的版本控制领域最酷的工作流增强。本质上,当你的工作目录在草稿变更集之上有未提交的修改时,你可以运行hg absorb,这些未提交的修改会被自动地神奇地合并(“吸收”)到相应的草稿祖先变更集中。这相当于无需手动提交或手动制定历史修改规则,就能完成hg histedit+ “roll” 操作。该命令会查看被修改的行,找到修改这些行的变更集,然后修改该变更集以纳入你的未提交修改。如果修改无法在没有冲突的情况下完成,它们会保持未提交状态。这个工作流对于应用审查反馈等场景极为有用。你只需修改文件,运行hg absorb,修改与提交的映射关系就会自动搞定。简直神奇。
一句话介绍
你有一个包含几个提交的特性分支。你的同事审查了该分支并指出了一些 bug。你修复了这些 bug,但不想把它们全部塞进一个含义不明的 fixes 提交中,因为你信奉原子提交。与其手动查找提交 SHA 来执行 git commit --fixup,或者手动运行交互式 rebase,不如这样做:
git add $FILES_YOU_FIXED git absorb --and-rebase
git absorb 会自动识别哪些提交是可以安全修改的,以及哪些暂存的变更属于这些提交中的哪一个。然后它会为每个变更写出 fixup! 提交。使用 --and-rebase 标志后,这些修复提交会自动合并到对应的提交中。
或者,如果你不放心,可以手动检查其输出,然后使用 git 内置的自动压缩功能(https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt—autosquash)将这些修复提交压缩到你的特性分支中:
git add $FILES_YOU_FIXED git absorb git log # 检查自动生成的修复提交 git rebase -i --autosquash master
安装
安装 git absorb 最简单的方法是从最新的 tagged release(https://github.com/tummychow/git-absorb/releases)下载构建产物。这些产物适用于 Windows、macOS 和 Linux(基于 Ubuntu 构建,静态链接 libgit2)。
如果你需要尚未发布的某个提交,请查看最新的 CI 制品(https://github.com/tummychow/git-absorb/actions/workflows/build.yml?query=event%3Apush+branch%3Amaster)或提交一个 issue。
另外,git absorb 也可以通过以下系统包管理器获取:
| 仓库 | 命令 |
|---|---|
| Arch Linux | pacman -S git-absorb |
| Debian | apt install git-absorb |
| DPorts | pkg install git-absorb |
| Fedora | dnf install git-absorb |
| Flox | flox install git-absorb |
| FreeBSD Ports | pkg install git-absorb |
| Homebrew 和 Linuxbrew | brew install git-absorb |
| MacPorts | sudo port install git-absorb |
| nixpkgs stable 和 unstable | nix-env -iA nixpkgs.git-absorb |
| openSUSE | zypper install git-absorb |
| Ubuntu | apt install git-absorb |
| Void Linux | xbps-install -S git-absorb |
| GNU Guix | guix install git-absorb |
| Windows Package Manager | winget install tummychow.git-absorb |
从源码编译
crates.io 徽章(https://crates.io/crates/git-absorb) 构建状态(https://github.com/tummychow/git-absorb/actions/workflows/build.yml)
你需要以下工具:
- cargo(https://github.com/rust-lang/cargo)
然后执行 cargo install git-absorb。确保 $CARGO_HOME/bin 在你的 $PATH 中,这样 git 才能找到该命令。($CARGO_HOME 默认是 ~/.cargo。)
请注意,git absorb 并不使用系统自带的 libgit2。这意味着你不需要安装 libgit2 来构建或运行它。不过,这也意味着你必须能够构建 libgit2。(由于 git2 crate 最近的变更(https://github.com/alexcrichton/git2-rs/commit/76f4b74aef2bc2a54906ddcbf7fbe0018936a69d),不再需要 CMake 来构建它。)
注意:cargo install 目前不知道如何安装 man 手册页(cargo#2729(https://github.com/rust-lang/cargo/issues/2729)),所以如果你使用 cargo 安装,git absorb --help 将无法正常工作。有两个手动解决方法,假设你的系统有 ~/.local/share/man/man1 目录并且 man --path 知道它:
-
从源码构建 man 手册页并复制 这需要你的系统上安装了 a2x(https://asciidoc-py.github.io/a2x.1.html)工具。
bash cd ./Documentation make mv git-absorb.1 ~/.local/share/man/man1 -
下载最近构建好的 man 手册页
- 按照上面的 安装 部分找到最近的构建
- 下载
git-absorb.1文件并解压缩 - 将其移动到
~/.local/share/man/man1
使用方法
- 执行
git add添加任何你想要吸收的变更。按照设计,git absorb只会考虑 git 索引(暂存区)中的内容。 - 执行
git absorb。这将在HEAD上创建一系列提交。每个提交都有一个fixup!消息,表明它应该被压缩到的目标提交的消息(如果唯一)或 SHA。 - 如果对输出满意,执行
git rebase -i --autosquash将fixup!提交压缩到它们的前驱提交中。如果你不需要编辑 rebase TODO 文件,可以设置GIT_SEQUENCE_EDITOR(https://stackoverflow.com/a/29094904)环境变量。 - 如果不满意(或者发生了意外),执行
git reset --soft PRE_ABSORB_HEAD可以重置到吸收前的提交并恢复旧状态。(你也可以通过git reflog找到相关提交。)如果你认为是git absorb的问题,请提交一个 issue(https://github.com/tummychow/git-absorb/issues/new)。
工作原理(大致)
git absorb 通过检查两个补丁 P1 和 P2 是否可交换(即先应用 P1 再应用 P2 是否与先应用 P2 再应用 P1 得到相同结果)来工作。git absorb 考虑一个以 HEAD 结尾的提交范围。第一个提交可以通过 --base <提交> 明确指定。默认情况下,会考虑最近 10 个提交(关于如何更改此设置,请参见 git-absorb.adoc 中的 STACK SIZE)。
对于索引中的每个块(hunk),git absorb 会检查该块是否与最后一个提交可交换,然后是前一个,依此类推。当它找到一个与该块不可交换的提交时,就推断出这是此变更的正确父提交,并将该块转换为一个 fixup 提交。如果该块与范围内的所有提交都可交换,则意味着我们没有为此变更找到合适的父提交;会显示一条警告,并且该块会保持在索引中未提交状态。
文档
关于 git-absorb 的更多信息,包括所有参数和配置选项,请参见 Documentation/git-absorb.adoc,或 git-absorb 的手册页。
待办事项
- 实现远程默认分支检查
- 停止使用
failure::err_msg,确保所有错误输出对用户有可操作性 - 在成功情况下增加更多日志输出
- 更多测试(尤其是主模块和集成测试)
- 记录堆栈和可交换性细节
- 更多可交换性情况(特别是复制/重命名检测)
- 不要同时将所有的 hunk 加载到内存中,因为它们可能非常大
- 实现某种索引锁定机制以保护免受并发修改
相似文章
Git history 命令值得更多关注
文章重点介绍了新的 `git history` 命令及其 `fixup`、`reword` 和 `split` 子命令,这些命令提供了原子化且感知分支的提交历史编辑功能,带来了类似 jj 的益处,而无需切换版本控制系统。
Show HN: Codiff,本地差异审查工具
Codiff 是一款轻量级本地 diff 查看器,用于审查 Git 暂存和未暂存的更改,支持基于 LLM 的逐步讲解和内联审查评论。
使用 git rebase --onto 更新堆叠的拉取请求
解释如何在父提交被压缩或替换时,使用 `git rebase --onto` 更新堆叠的拉取请求。
在$dayjob审查所谓的Pull Requests
一位开发者描述了他使用git命令(如range-diff和log -p)来审查pull requests的工作流程,以规避基于Web的UI的缺陷。
Git-Assistant: 基于规划的 Git 仓库更新支持
Git-Assistant 是一款人工智能工具,它将大型语言模型与自动化规划相结合,帮助开发者更安全、更可靠地执行复杂的 Git 操作。