在 gitoxide 仓库中使用 Tix 编辑提交历史与修复 CI:Agent 级操作全指南

原创2026-10-02 01:19:361,440 阅读
文章标签:版本控制CLI

在 gitoxide 仓库中使用 Tix 编辑提交历史与修复 CI:Agent 级操作全指南

本文以 gitoxide 仓库中面向 Agent 的 Tix 技能文档 为核心,系统讲解如何用 Tix 安全地改写提交历史、修复 CI 失败,同时保留人类审阅状态(✨ 补丁审阅标记与 ✔️ 检查通过标记)。读完本文,你将掌握 tix travel、tix amend --index、tix new、tix reword、tix enrich commit note 以及 tix rebase-update <a href="https://link.gitcode.com/i/6c2c27484acf607c3ecb9222f4fbbd5d" target="_blank">FILE] 的完整操作纪律,并理解其底层实现依据([Tix 行为规范 与 enrich 命令源码)。

认识 Tix:为大型仓库而生的提交历史浏览器

Tix 是 gitoxide 仓库中一个 tig 风格的程序,按照 gix-tix/README.md 的描述,它的设计初衷是展示项目历史、允许裁剪视图以隐藏指定分支、复制选中 hash,并且"在查看大型仓库时比 tig 更快、更省内存"。其行为契约由 gix-tix/spec.md 统一定义:它是一个"极简的、tig 启发的、为大型仓库优化的提交历史浏览器",必须在 Linux 内核级别的历史规模下保持可用,不能为了不可见的元数据牺牲响应性。

在 Agent 工作流中,Tix 与 Git 有明确的分工:

"Use Tix for history mutations and Git for inspection and staging."

即 Tix 负责一切历史变更(历史变更、改写、重放),Git 负责检视与暂存。同时,技能文档明确强调:用户指令决定操作范围、签名、QA 与推送;这份技能本身不授予任何额外授权。换句话说,Tix 是执行工具,操作的合法边界始终来自用户的明确要求。

Tix 的命令面相当完整,spec.md 列出了 tix [REVISION]...(浏览)、tix show(打印完整历史视图)、tix travel(时间旅行式检出)、tix stash、tix rebase todo/apply、tix enrich、tix new/reword/amend 等子命令。本文聚焦于 SKILL.md 所规范的"编辑既有提交 + 修复 CI"场景。

动手前:检查、选择与状态判定

任何历史变更之前,必须建立对当前状态的完整认知:

git status --porcelain=v1 --branch
tix show

记录三项基准信息:起始分支、起始 hash、起始 change ID。由于仓库中可能同时有其他 Agent 在工作,每次变更前都应重新检查状态,必要时等待其他 Agent 的操作落定。

Tix 会在每个提交 hash 后显示一个 change ID。根据 spec.md 的定义,每个七字符提交 hash 之后紧跟一个七字符 reverse-hex(逆序十六进制)change ID,两者宽度相等;发生前缀冲突或重复时,行首会出现 💥 沟槽标记。技能文档给出了一个重要建议:后续旅行(travel)时优先使用 change ID 而不是 hash,因为编辑与重放过程中 hash 会变化,而 change ID 在提交被改写后依然稳定(spec.md 说明 enrichment 正是以"提交的有效 change ID"为键存储的)。

另一个必须理解的概念是 pending replay(待处理重放):当某个祖先提交被编辑后,Tix 可能不会立即把后代提交的变更重放到编辑后的历史上,而是推迟到 tix travel 到达它们时才执行。因此,在编辑祖先内容后查看 tix show,某些审查标记可能暂时"消失",这属于正常现象,不应据此误判。

任务决策表:amend、fixup、reword 还是 new?

SKILL.md 给出了一个核心决策表,它决定了不同任务对应的默认动作:

Task Default action
Add independent work Create a new commit.
Change only a message Reword the requested target directly.
Change a commit's contents without ✨ Amend it directly; do not create a fixup, regardless of other enrichments.
Change a commit's contents with ✨ Preserve it; insert a fixup! immediately above it.

理解这张表的前提是理解两个审查标记:

  • ✨:补丁审阅/重构批准标记,由人类审阅者在 Tix change 中通过 tix enrich patch refackiewed 设置。只有人类审阅者才能显式设置或清除该标记——Agent 严禁调用该命令(包括 --clear),Agent 自己的审阅、检查通过、正面反馈或收尾请求都不构成授权依据。
  • ✔️:记录"某个精确树"的检查通过状态,由 tix enrich tree checks-pass 管理。它不暗示审阅通过,审阅标记也不代表检查通过,两者互不蕴含。

如果用户指令与决策表冲突,以用户的显式指令为准;除非用户明确要求,否则不要 squash fixup。变更之后不得伪造任何标记,也不得把一次聚焦测试当作完整的 QA 画像。

底层实现:enrichment 的存储机制

这两个标记(连同 🚧 todo、📝 note)属于 Tix 的 enrichment 机制,其实现可在 gix-tix/src/enrich.rs 中确认。根据 spec.md:

  • 提交级 enrichment 存储在 worktree 本地的 refs/worktree/tix/enrich Git notes 中,以提交的有效 change ID 为键,使用人类可读的 Git config 格式:独立的 [commit] 键保存 todo = true 和可选的多行 note 值;
  • 树级 enrichment 存储在 refs/worktree/tix/enrich-tree notes 中,直接以 tree object ID 为键,[tree] checks-pass = true 因而适用于每个拥有该精确树的提交,并且一旦改写改变了树,标记自然消失。

对应地,command/enrich.rs 中的子命令结构为:tix enrich commit todo|note|git-note 与 tix enrich tree checks-pass,布尔型命令幂等地设置或清除标记,note 命令调用 Git 编辑器、删除空 note、对未变更的 note 不做改动,且所有命令的目标默认是 HEAD,也接受 Git revspec 或无歧义的 change ID 前缀。

编辑命令实战:travel、amend、new、fixup、reword

切换目标提交:tix travel

对于内容编辑,必须从干净的 index 与 worktree 出发,先旅行到目标提交,确认 HEAD 正确后再编辑:

tix travel "$target_change"

旅行到目标后执行聚焦验证。当 HEAD 正确时,其他 Agent 的未暂存变更不需要旅行或清理:只暂存自己拥有的路径/hunk,新文件必须显式加入。

修改提交内容:tix amend --index

tix amend --index

--index 是必须的:否则当 index 与 HEAD 相同时,amend 和 new 会回退到已跟踪的 worktree 变更(未跟踪文件不会被隐式包含)。--index 消费整个 index,因此如果存在他人无关的暂存变更,需要先协调。该行为与 spec.md 一致:命令行 tix amend --index 禁用 worktree 回退,仅当 index 有暂存内容时改写 @ 提交,否则报告 nothing to amend。

创建 fixup:生成精确首行 + 新建提交

当目标提交带有 ✨ 标记而必须保留时,在旅行到目标之后,用如下命令生成 fixup 的精确第一行:

git show -s --format='fixup! %s' HEAD > "$message_file"

注意:不要从 tix show 复制主题行,因为 tix show 渲染 Markdown,可能省略字面反引号。也没有 tix new --fixup 这样的旗标。

接着追加一个空行,并在消息中说明失败原因、修正内容与验证结果,然后使用完整的消息文件并以负责 Agent 的真实姓名/邮箱作为作者:

tix new --index --author "$agent_author" --file "$message_file"

创建 fixup 后,记录其新 change ID 作为 fixup_change,并给它添加一条 Tix note,note 中只包含"如果这个 fixup 是普通提交时它应有的单行标题"。解释保留在提交体里,提交主题保持精确的 fixup! <original subject>。note 文件必须放在检出目录之外(旧提交处文件可能消失),再通过 Git 编辑器非交互地保存:

TIX_FIXUP_NOTE_FILE="$note_file" GIT_EDITOR='cp "$TIX_FIXUP_NOTE_FILE"' \
  tix enrich commit note "$fixup_change"

tix enrich commit note 没有 --message 或 --file 旗标。必须先确认 enrichment 成功再继续;若失败,应直接在现有 fixup 上补完 note,而不是另建提交。

仅修改消息:tix reword

tix reword "$target_change" --file "$message_file"

先检视目标内容,再提供其完整替换消息。即使 HEAD 移动了也要忠实于显式目标;基于文件的消息会保留 enrichment。单纯润色文字不转移作者权,只有内容责任发生变化时才用 --author 指定作者(例如 tix reword --author "Agent Name <agent@example.com>",见 gix-tix/AGENTS.md)。

临时禁用提交签名

当签名被禁用时,既有工作流使用命令级前缀(同样适用于 new 与 reword):

GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=commit.gpgSign GIT_CONFIG_VALUE_0=false tix amend --index

关键是保留任何既有配置覆盖项,不要覆盖它们,也不要修改持久化的 Git 配置。

相关源码与仓库纪律佐证

  • command/enrich.rs 的测试 boolean_enrichments_are_idempotent_and_target_the_selected_commit 证实:todo 与 checks-pass 标记的设置/清除是幂等的,且只作用于目标提交,默认 HEAD 不被波及;
  • command/enrich.rs 的测试 editors_preserve_other_enrichments 证实:编辑 note 会保留 todo 标记,Tix note 与普通 Git note 均使用编辑器输出;
  • gix-tix/AGENTS.md 记录了 gix-tix 目录专属的 provisional commit 规则:开始修改跟踪文件前,从干净 worktree 创建一个以 🚧WIP🚧 <wip@invalid> 为作者的临时空提交;任务完成后暂存变更并 amend 该提交,把作者替换为负责 Agent 的真实身份、更新主题与正文,最终提交必须包含完整任务且 worktree 干净。SKILL.md 特别提醒:这条规则只适用于 gix-tix/ 目录下的编辑,并非每次 Tix 操作都要遵守。

tix rebase-update [FILE]:把可见栈更新到新基

tix rebase-update 是技能层级的命令而非字面安装的 Tix 子命令:当用户在请求中提到它时,它的含义是"把当前可见栈更新到更新的隐藏本地分支 tip 上",底层通过 tix rebase todo --update-base 实现。可选的 FILE 是要保留的 todo 路径;未提供时,在检出目录之外创建任务专属的临时文件,成功后删除。

开始前依次刷新以下信息:

git status --porcelain=v1 --branch
tix show
tix rebase todo --help

不得带着未合并条目、或带着无关的脏 index/worktree 开始**——rebase 可能同时需要它们来做冲突恢复。也不要仅仅为了让检出变干净就去 stash、丢弃或吸收其他 Agent 的变更。

先生成计划而不立即应用:

tix rebase todo --update-base > "$todo_file"

必须等生成成功,并完整阅读计划。保留每一个可见提交、fork、ref 以及生成的 @ 检出目标,除非用户显式要求额外历史编辑。不要手工构造新基,也不要用猜测的 --onto 替代 --update-base。应用审阅过的文件并选择可恢复的冲突:

tix rebase apply --materialize-conflicts "$todo_file"

应用成功即更新完成。只有当 Tix 报告保存了操作且 index 中存在未合并条目时,才接受冲突。此时检查 tix rebase status、git diff --cc 以及 index 阶段 :1:、:2:、:3:,保留双方的提交意图,只暂存解决方案,然后继续:

tix rebase continue --materialize-conflicts

后续每个冲突重复"检查 → 解决 → 继续"的循环。铁律包括:操作已保存后绝不重跑原始 todo;绝不用 tix amend 记录 rebase 冲突;除非用户要求保留部分结果并放弃剩余操作,否则不调用 tix rebase stop。

完成后验证:tix rebase status 无已保存操作,git status --porcelain=v1 --branch 与 tix show 正常,确认更新的隐藏基在祖先链中、预期的检出与 refs 已恢复、所有原始可见变更仍被表示、且没有无关文件进入被改写的提交。若提供了 FILE 就保留它,否则只删除任务专属的临时 todo。

从实现看,--update-base 与 --onto 互斥,且"没有可用的更新目标 tip"属于错误(spec.md);默认情况下 todo 冲突不改变任何东西,显式 --materialize-conflicts <a href="https://link.gitcode.com/i/8747c9678d1402740f913871c1eba927" target="_blank">CONTINUE] 才接受部分结果、检出冲突提交(带未合并 index)并写出新的可编辑续接 todo,且以非零退出码结束,防止脚本把未完成的 rebase 误认为完成([spec.md)。

重放与恢复(Replay and Recovery)

编辑可以先行推进 refs,而把后代变更留到稍后重放。完成祖先编辑任务后,用 tix travel "$return_branch" 重放祖先链并恢复附着状态;如果初始是 detached,则通过保存的 change ID(而非过期的 hash)返回。尊重用户后续的检出变更:直接目标的 reword 并不因祖先被改写而必须旅行回去。针管理(pin)交给 Tix 的正常命令。

若 travel 报告重放冲突但没有改变文件,使用:

tix travel --materialize-conflicts "$target_change"

它刻意以非零退出码结束,且必须对应未合并的 index。检查 git diff --cc 与阶段 :1: :2: :3:,保留双方提交意图;暂存解决结果后 tix amend --index,再重试 travel——仅暂存是不完整的。

其他失败后先检查状态,修正环境问题再重试;绝不重复已成功的变更,也不要用 reset 替代诊断。不要自动 stash 或吸收其他 Agent 的工作;旅行前完成已授权、任务专属的变更,或保留验证过的补丁/副本(含未跟踪文件)。tix stash 与 travel --stash 是可选项。应用失败后,先保留恢复提交、检查已应用了什么,再恢复任何东西。消息与恢复材料放在检出目录之外。

验证与收尾(Validate and Finish)

保持提交自包含。对 CI 修复,运行聚焦检查,并把取消导致的干扰与真实失败区分开。用户明确要求全面 sweep 时,遵循 tix-qa-sweep 技能:它按从旧到新的顺序访问每个没有 ✔️ 标记的可见提交,先确定 Fast(格式化、lint、类型、静态/依赖检查)或 Thorough(加上构建、测试、文档与集成检查)画像,再在每次修复后用 tix enrich tree checks-pass 标记通过的树,全程保留用户的排除项、审查保留规则与 QA 级别。不要在每次修复后自动启动完整 QA。

复用构建缓存:不删除缓存、不禁用增量编译、不把已授权的增长当作附带清理。完成后返回请求的检出位置,核验状态、位置、diff 与最新的 tix show;保留未被触碰的审查标记,不要重建已失效的标记。存在并发工作时,只验证预期变更是否被提交,而不是强行让一切变干净。

最终报告应给出:最终 hash/change ID、验证结果与推送状态(包括远端 CI 仍在测试更旧 head 的情形);成功后只删除任务专属的临时文件,中断时保留恢复材料。

小结

Tix 把 gitoxide 仓库的提交历史编辑变成一套可审计、可恢复的纪律性操作:以 change ID 为锚点旅行,按审阅状态(✨)决定 amend 还是 fixup,用文件化消息保留 enrichment,用 tix rebase todo --update-base 与 tix rebase apply --materialize-conflicts 完成可见栈更新,最后以 tix enrich tree checks-pass 与聚焦 QA 收尾。其所有行为都有 gix-tix/spec.md 与 gix-tix/src 下的源码与测试背书,本文给出的命令序列可直接在当前仓库或任何使用 Tix 管理的仓库中执行。

登录后查看全文
gitoxide