git-absorb:自动的git commit --fixup

Lobsters Hottest 工具

摘要

git-absorb自动为暂存的更改创建fixup提交,实现了与hg absorb类似的功能。它与git的autosquash集成,简化了应用代码审查反馈的过程,无需手动查找提交的SHA。

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

缓存时间: 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 Linuxpacman -S git-absorb
Debianapt install git-absorb
DPortspkg install git-absorb
Fedoradnf install git-absorb
Floxflox install git-absorb
FreeBSD Portspkg install git-absorb
Homebrew 和 Linuxbrewbrew install git-absorb
MacPortssudo port install git-absorb
nixpkgs stable 和 unstablenix-env -iA nixpkgs.git-absorb
openSUSEzypper install git-absorb
Ubuntuapt install git-absorb
Void Linuxxbps-install -S git-absorb
GNU Guixguix install git-absorb
Windows Package Managerwinget 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 知道它:

  1. 从源码构建 man 手册页并复制 这需要你的系统上安装了 a2x(https://asciidoc-py.github.io/a2x.1.html)工具。

    bash cd ./Documentation make mv git-absorb.1 ~/.local/share/man/man1

  2. 下载最近构建好的 man 手册页

    1. 按照上面的 安装 部分找到最近的构建
    2. 下载 git-absorb.1 文件并解压缩
    3. 将其移动到 ~/.local/share/man/man1

使用方法

  1. 执行 git add 添加任何你想要吸收的变更。按照设计,git absorb 只会考虑 git 索引(暂存区)中的内容。
  2. 执行 git absorb。这将在 HEAD 上创建一系列提交。每个提交都有一个 fixup! 消息,表明它应该被压缩到的目标提交的消息(如果唯一)或 SHA。
  3. 如果对输出满意,执行 git rebase -i --autosquashfixup! 提交压缩到它们的前驱提交中。如果你不需要编辑 rebase TODO 文件,可以设置 GIT_SEQUENCE_EDITOR(https://stackoverflow.com/a/29094904)环境变量。
  4. 如果不满意(或者发生了意外),执行 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 命令值得更多关注

Hacker News Top

文章重点介绍了新的 `git history` 命令及其 `fixup`、`reword` 和 `split` 子命令,这些命令提供了原子化且感知分支的提交历史编辑功能,带来了类似 jj 的益处,而无需切换版本控制系统。

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

Hacker News Top

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

在$dayjob审查所谓的Pull Requests

Lobsters Hottest

一位开发者描述了他使用git命令(如range-diff和log -p)来审查pull requests的工作流程,以规避基于Web的UI的缺陷。