Git 2.54 和 2.55:探索实验性的 `git history` 命令

Git 2.54 和 2.55:探索实验性的 git history 命令

git history 命令在 Git 2.54 和 2.55 版本中引入,提供了一种流线型、原子化的方式来修改旧提交,而无需 git rebase -i 那样繁琐的手动操作。通过自动对后代分支进行变基(rebasing),它将一些在 Jujutsu (jj) 等替代版本控制系统中常见的高级历史管理功能直接引入了 Git 核心发行版中。

使用 git history 进行原子化历史修改

git history 的设计目标是原子性:它要么完全成功,要么不执行任何操作。为了防止工作树处于损坏或冲突的状态,该命令会拒绝任何会导致合并冲突的操作。这与标准的交互式变基有显著不同,后者可能会暂停以进行手动冲突解决。

git history fixup

git history fixup <commit> 允许用户将暂存的更改合并到之前的提交中。它的功能类似于 git commit --fixup 和 autosquash rebase 的组合,但具有更广泛的分支更新范围。

虽然 git rebase --update-refs 仅移动活动变基范围内的引用,但 git history fixup 会识别并重写从目标提交开始的所有后代本地分支。这确保了所有相关的特性分支都能与修复保持同步。

局限性:

  • 在存在合并提交(merge commits)的情况下无法工作。
  • 无法处理会导致冲突的操作。

git history reword

git history reword <commit> 会更新特定提交的提交信息。它会打开用户的编辑器来修改信息,保存更改后,并在其上方重新构建剩余的提交栈。

由于此操作仅修改提交信息而不修改文件内容,因此它不会触及索引(index)或工作树。这允许用户在不干扰当前工作的情况下,重写当前未检出的分支上的提交。

git history split

git history split <commit> 将单个提交拆分为两个独立的提交。该过程是交互式的,使用逐块(hunk-by-hunk)提示(类似于 git add -p)让用户选择哪些更改属于第一个提交,哪些属于第二个提交。

git rebase -i 和 Jujutsu (jj) 的对比

git history 将交互式变基中最常见的几种用例简化为了低摩擦、单一用途的命令。然而,它并不是其他系统中更强大工具的完全替代品。

特性 git history git rebase -i Jujutsu (jj)
原子操作 是(如果冲突则失败) 否(暂停以解决冲突) 是(冲突是头等公民)
自动更新后代 是(所有本地分支) 有限 (--update-refs) 原生
工作树影响 极小(针对 reword/split) 高(重写树) 工作副本即提交
复杂度 低(单一命令) 高(手动编辑列表) 中(新的思维模型)

社区见解与实际考量

社区讨论强调了在使用这些新命令时的一些关键权衡和用户的体验:

历史整理的价值

一些开发者认为完美地整理 Git 历史是不必要的,建议在合并之前 squash 所有提交是一种更高效的方法。其他人则认为这些工具是...

Sources