网易首页 > 网易号 > 正文 申请入驻

一个提交里塞了五处改动,怎么只拆出你要的那两处?

0
分享至

下午就要合一个 bug 修复,它偏偏和一处你想先吵一架的重构躺在同一个提交里。Agent 给这个提交起的名字叫Update checkout,动了五个文件。其中两个修的是客户今天就能看见的格式 bug,还配了测试;另外三个把写死的税率挪到接口后面,顺手把测试也重写了。这个提交只给你两个按钮:全要,或者全不要。


写代码的 agent 很容易走到这一步——任务说的是"清理 checkout",它一路上碰过的东西就全进了一个提交。放在以前,想把它拆开只能上交互式 rebase:标记edit、reset、分块重新暂存、提交两次、continue。

Git 2.54(2026 年 4 月发布)加了一条实验性命令专门干这个:git history split。你像用git add -p那样挑 hunk,Git 把它们写进一个新的父提交,所有建在其上的分支被移到重写后的历史上。没有待办清单,也不会卡在 rebase 进行中。

下面用一个一次性仓库复现:造一个 agent 风格的巨型提交,把它拆开,再用reword改消息、用fixup修补一个旧提交。

先把烂摊子故意造出来

split 和 reword 需要 Git 2.54 或更新,fixup 需要 2.55。用git --version确认。文件是几个小 PHP 类,但你不需要装 PHP 或 PHPUnit——Git 只认文本。

先在 main 上放起点。Money::format有个真 bug:1205 分输出成 12.5,因为分位没有补零。初始化仓库、建好 src 和 tests 目录、提交一个 "Initial checkout"。

然后扮演 agent。在任务分支上,一个提交同时修了补零、加了回归测试、抽出TaxRate接口、让 Checkout 依赖它、重写 Checkout 测试。接着第二个更小的提交落在上面,消息什么也没说。跑git show --stat HEAD~1,问题一目了然:五个文件、一条消息、两件不相干的事。

动手重写之前,先打个标签记住起点:git tag before-split。用标签,别用分支。默认情况下 git history 会移动所有从被重写提交派生出来的本地分支,放在顶端的备份分支会被一起挪走;而标签会留在你放它的地方。

用 git history split 拆开

把 split 指向那个巨型提交。它在顶端下面一个,正是以前需要 rebase 的场景:git history split HEAD~1。

Git 按路径顺序遍历这个提交的 hunk,逐个询问,按键和git add -p一样。y把 hunk 移进新提交,n留在原地,d连同该文件剩下的部分一起留下。对这个提交来说,选择是:

  • src/Checkout.php:d
  • src/Money.php:y
  • src/TaxRate.php:d
  • tests/CheckoutTest.php:d
  • tests/MoneyTest.php:y

然后编辑器会打开两次,两次都从 agent 的原始消息开始。第一次是给拆出来的那个提交——你挑中的 hunk,它成为新的父提交,写Fix zero-padding in Money::format。第二次是给留在原提交里的部分,写Extract TaxRate port from Checkout。作者身份保留原提交的作者。

如果两件事本来就分在不同文件里,用 pathspec 就能省掉按 d 的功夫,只有匹配的文件会被拿出来,其余留在原提交:git history split HEAD~1 -- src/Money.php tests/MoneyTest.php。

注意你没拆出去的东西:Checkout 测试的重写。旧测试调用new Checkout()不带参数,构造函数一旦需要 TaxRate 就会立刻崩。一个同时装着重构和旧测试的提交会让测试套件变红。重写后的测试要跟着逼它改的那处改动走。按"评审者会一起通过"的标准给 hunk 分组。

一个提交进去,两个提交出来:修复成为父提交,重构坐在它上面。接着确认什么都没丢:git log --oneline main..agent/checkout和git diff before-split agent/checkout。日志显示三个提交,原来是两个;diff 应该什么都不打印。split 只是重新分配 hunk,顶端代码不变。

第一次在真实分支上做?加上--dry-run。Git 会写出新对象但不移动任何 ref,并按git update-ref能读的格式打印 ref 更新。只想移动当前分支,就传--update-refs=head。

不用 rebase 的 reword 和 fixup

那个 "more fixes" 提交还在顶上。git history reword会在编辑器里打开任意提交的消息并就地重写,不碰工作区和索引,甚至在裸仓库里也能用。把它改成Document the TaxRate dependency in README。对 HEAD 来说,git commit --amend效果一样;reword 是给三四个提交之前、amend 够不着的地方用的。

然后评审发现一个缺口:修复没有覆盖金额小于 1.00 的测试。Git 2.55 加了git history fixup,把你暂存的改动折进更早的提交,再把后面的重放上去:git history fixup 'agent/checkout^{/Fix zero}'。这个^{/Fix zero}后缀会找到分支上消息匹配的最新提交。修复提交保留自己的消息和作者;想改消息就加--reedit-message。Git 2.56 加了git history drop,删掉一个提交并把它的后代重放到其父提交上。

如果 agent/checkout 已经推过,这些和任何 rebase 一样都是重写:用git push --force-with-lease推。想整个丢掉这次练习,在分支上执行git reset --hard before-split就回去了。

git history 拒绝做的事

手册页对限制写得很直白,而且大多是有意为之:

  • 不碰含合并提交的历史,那种情况用git rebase --rebase-merges
  • 任何会以合并冲突收尾的操作都会被拒绝。历史重写不该把你留在半成品状态,所以它直接中止,而不是中途停下。
  • Git 钩子"在当前时间点"不会运行。如果 commit-msg 钩子检查消息格式,它看不到你在 split 期间输入的消息。
  • 源码调用 hunk 选择器时禁用了编辑,所以不提供e。当一处修复和一处重构共享同一个 hunk,试试s把它切成更小的 hunk,或者退回git rebase -i

全选或全不选也是无效的,因为两个提交里会有一个是空的。截至 2.56,整条命令仍标记为实验性,并警告行为可能变化。要重排一段范围或把它移到新基底上,git rebase仍是那个工具;git history 一次只覆盖一处有针对性的编辑。

挑哪些 hunk 该在一起,是拆分里最难的部分,而 agent 的单个提交不会告诉你它按什么顺序干活。如果 agent 在一个回合里做了补零修复、下一个回合做重构,按回合看就能在你敲 pathspec 之前把路径给你。要是在 agent 提交之前就打开评审台,还能逐个文件暂存和提交,那就没什么可拆的了。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
难以置信!100元剪一整年头发,广东一理发店推出包年套餐,评论区炸锅

难以置信!100元剪一整年头发,广东一理发店推出包年套餐,评论区炸锅

火山詩话
2026-10-17 20:44:09
演完张凌赫母亲,又演田曦薇生母,古装女神毛林林又凭实力圈粉

演完张凌赫母亲,又演田曦薇生母,古装女神毛林林又凭实力圈粉

两只米老鼠
2026-10-17 19:40:39
气血不足百病生!提醒中老年,少吃花生红枣,多吃3样,气血双补

气血不足百病生!提醒中老年,少吃花生红枣,多吃3样,气血双补

江江食研社
2026-10-14 17:30:11
看完铁人4-0海牛!不得不承认的5个事实,铁人保级基本没悬念!

看完铁人4-0海牛!不得不承认的5个事实,铁人保级基本没悬念!

墨史轩
2026-10-17 22:25:16
迈阿密主帅:梅西将去西班牙参加颁奖典礼,俱乐部同意他前往

迈阿密主帅:梅西将去西班牙参加颁奖典礼,俱乐部同意他前往

懂球帝
2026-10-17 10:25:11
卡塔尔媒体:这支中国U16实力太强,完全是碾压我们,他们能夺冠

卡塔尔媒体:这支中国U16实力太强,完全是碾压我们,他们能夺冠

稗官青史
2026-10-17 17:14:00
上海徐浦大桥发生惨烈车祸,变道致多车相撞有死伤!监控画面曝出

上海徐浦大桥发生惨烈车祸,变道致多车相撞有死伤!监控画面曝出

胡侃社会百态
2026-10-17 18:38:26
俞飞鸿帮闺蜜向谢霆锋索要南昌演唱会门票被拒,谢霆锋回复超好笑

俞飞鸿帮闺蜜向谢霆锋索要南昌演唱会门票被拒,谢霆锋回复超好笑

娱最资讯
2026-10-17 21:17:57
16GB+1TB!新机官宣:10月15日,首发上市!

16GB+1TB!新机官宣:10月15日,首发上市!

科技堡垒
2026-10-15 12:08:00
比造船还赚钱!中国船厂成韩国船机“大客户”

比造船还赚钱!中国船厂成韩国船机“大客户”

国际船舶网
2026-10-17 14:43:20
不是迷信!九月初九重阳节,这5件事最忌讳,千万别忘告诉家人

不是迷信!九月初九重阳节,这5件事最忌讳,千万别忘告诉家人

简食记工作号
2026-10-17 00:50:49
被骂“丢人现眼”!30岁国脚暴怒:冲上去要和球迷对峙 拉都拉不住

被骂“丢人现眼”!30岁国脚暴怒:冲上去要和球迷对峙 拉都拉不住

念洲
2026-10-17 13:26:57
CCTV5+直播沪蓉大战!穆斯卡特反问成都记者:一会能否告诉我蓉城的伤情?

CCTV5+直播沪蓉大战!穆斯卡特反问成都记者:一会能否告诉我蓉城的伤情?

刀锋体育
2026-10-17 18:01:38
叶檀老师,我生病了,一身债,想把自己的两个娃托付您……丨叶檀回信

叶檀老师,我生病了,一身债,想把自己的两个娃托付您……丨叶檀回信

叶檀财经
2026-10-17 18:55:06
饭馆强制交社保的死循环:老板涨成本,员工降收入,最后小店关门

饭馆强制交社保的死循环:老板涨成本,员工降收入,最后小店关门

笔墨V
2026-10-17 11:35:51
A股:全体股民提前做好准备了,后天周一10.19,A股或迎来修复行情?

A股:全体股民提前做好准备了,后天周一10.19,A股或迎来修复行情?

风风顺
2026-10-18 00:00:07
铁饭碗要碎了!事业单位开始搞全员竞聘上岗!

铁饭碗要碎了!事业单位开始搞全员竞聘上岗!

职场资深秘书
2026-10-15 20:20:34
辽宁队掀翻山东,乌戈后手再现,邱彪咋接招

辽宁队掀翻山东,乌戈后手再现,邱彪咋接招

体育篮球弟
2026-10-18 04:46:20
特斯拉降到22万以内,难受的不是对手,是上个月刚提车的人

特斯拉降到22万以内,难受的不是对手,是上个月刚提车的人

沙雕小琳琳
2026-10-17 14:39:48
美媒眼馋:中国造出了美国人喜欢的车,却不是给美国的

美媒眼馋:中国造出了美国人喜欢的车,却不是给美国的

观察者网
2026-10-15 20:04:24
2026-10-18 06:12:49
Ping值焦虑
Ping值焦虑
有态度网友ytd
202文章数 109关注度
往期回顾 全部

科技要闻

刘煜辉:99%的黄金分析师报告一钱不值

头条要闻

普京:包围并消灭2000人的乌军集群 这非比寻常

头条要闻

普京:包围并消灭2000人的乌军集群 这非比寻常

体育要闻

升级版杨瀚森再闯难关:当上开拓者第三中锋还得拼

娱乐要闻

庾澄庆罕谈前妻 撕下伊能静仅剩的体面

财经要闻

新一轮大跌源头,找到了!

汽车要闻

星瑞L PLUS限时售价10.97万元起 开启智混3L时代

态度原创

亲子
健康
时尚
本地
军事航空

亲子要闻

嘟嘟为了吃口雪糕能有多拼

看着很健康的人,怎么会突然猝死?

降落伞裤的3组搭配,打破秋冬沉闷感!

本地新闻

因新荣记出圈,这座浙东小城才是吃货天堂

军事要闻

“星盾”限速事件加剧美乌裂痕

无障碍浏览 进入关怀版